blob: 59f0595e34b560ab37cbe5f451dac4dbb089d8f2 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07002
Thomas Vachuskae0f804a2014-10-27 23:40:48 -07003import com.google.common.collect.ImmutableList;
4import com.google.common.collect.ImmutableMap;
5import com.google.common.collect.Lists;
6import com.google.common.collect.Sets;
7import com.google.common.util.concurrent.ListenableFuture;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07008import org.junit.After;
9import org.junit.Before;
10import org.junit.Test;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070011import org.onlab.onos.core.ApplicationId;
12import org.onlab.onos.core.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070013import org.onlab.onos.event.impl.TestEventDispatcher;
14import org.onlab.onos.net.DefaultDevice;
15import org.onlab.onos.net.Device;
16import org.onlab.onos.net.Device.Type;
17import org.onlab.onos.net.DeviceId;
18import org.onlab.onos.net.MastershipRole;
19import org.onlab.onos.net.Port;
20import org.onlab.onos.net.PortNumber;
21import org.onlab.onos.net.device.DeviceListener;
22import org.onlab.onos.net.device.DeviceService;
Jonathan Hart936c49d2014-10-23 16:38:59 -070023import org.onlab.onos.net.flow.BatchOperation;
alshabib193525b2014-10-08 18:58:03 -070024import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070025import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070026import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070027import org.onlab.onos.net.flow.FlowEntry;
28import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070029import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070030import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070031import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070032import org.onlab.onos.net.flow.FlowRuleEvent;
33import org.onlab.onos.net.flow.FlowRuleListener;
34import org.onlab.onos.net.flow.FlowRuleProvider;
35import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
36import org.onlab.onos.net.flow.FlowRuleProviderService;
37import org.onlab.onos.net.flow.FlowRuleService;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070038import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070039import org.onlab.onos.net.flow.TrafficSelector;
40import org.onlab.onos.net.flow.TrafficTreatment;
41import org.onlab.onos.net.flow.criteria.Criterion;
42import org.onlab.onos.net.flow.instructions.Instruction;
43import org.onlab.onos.net.provider.AbstractProvider;
44import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070045import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070046
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070047import java.util.ArrayList;
48import java.util.Arrays;
49import java.util.Collections;
50import java.util.HashMap;
51import java.util.List;
52import java.util.Map;
53import java.util.Set;
54import java.util.concurrent.ExecutionException;
55import java.util.concurrent.Executor;
56import java.util.concurrent.Future;
57import java.util.concurrent.TimeUnit;
58import java.util.concurrent.TimeoutException;
59
60import static org.junit.Assert.*;
61import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070062
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070063/**
64 * Test codifying the flow rule service & flow rule provider service contracts.
65 */
tom202175a2014-09-19 19:00:11 -070066public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070067
alshabib92c65ad2014-10-08 21:56:05 -070068
tomf6ab2152014-09-18 12:08:29 -070069 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070070 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070071 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070072 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070073 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070074
tom202175a2014-09-19 19:00:11 -070075 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070076
77 protected FlowRuleService service;
78 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070079 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070080 protected TestProvider provider;
81 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070082 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070083
84 @Before
85 public void setUp() {
tom202175a2014-09-19 19:00:11 -070086 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070087 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070088 mgr.eventDispatcher = new TestEventDispatcher();
89 mgr.deviceService = new TestDeviceService();
90 service = mgr;
91 registry = mgr;
92
93 mgr.activate();
94 mgr.addListener(listener);
95 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -070096 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -070097 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070098 assertTrue("provider should be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070099 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700100 }
101
102 @After
103 public void tearDown() {
104 registry.unregister(provider);
105 assertFalse("provider should not be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700106 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700107 service.removeListener(listener);
108 mgr.deactivate();
109 mgr.eventDispatcher = null;
110 mgr.deviceService = null;
111 }
112
113 private FlowRule flowRule(int tsval, int trval) {
114 TestSelector ts = new TestSelector(tsval);
115 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700116 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700117 }
118
alshabibbb8b1282014-09-22 17:00:18 -0700119
120 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700121 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700122 service.applyFlowRules(rule);
123
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700124 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700125 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700126 }
127
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700128 private void validateEvents(FlowRuleEvent.Type... events) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700129 if (events == null) {
130 assertTrue("events generated", listener.events.isEmpty());
131 }
132
133 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700134 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700135 for (FlowRuleEvent e : listener.events) {
136 assertTrue("unexpected event", e.type().equals(events[i]));
137 i++;
138 }
139
140 assertEquals("mispredicted number of events",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700141 events.length, listener.events.size());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700142
143 listener.events.clear();
144 }
145
146 private int flowCount() {
147 return Sets.newHashSet(service.getFlowEntries(DID)).size();
148 }
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700149
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700150 @Test
151 public void getFlowEntries() {
152 assertTrue("store should be empty",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700153 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700154 FlowRule f1 = addFlowRule(1);
155 FlowRule f2 = addFlowRule(2);
156
alshabib1c319ff2014-10-04 20:29:09 -0700157 FlowEntry fe1 = new DefaultFlowEntry(f1);
158 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700159 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700160
alshabib1c319ff2014-10-04 20:29:09 -0700161 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700162 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
163 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700164
165 addFlowRule(1);
166 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700167
alshabib1c319ff2014-10-04 20:29:09 -0700168 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700169 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700170 }
171
alshabibbb8b1282014-09-22 17:00:18 -0700172
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700173 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700174 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700175 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
176 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700177 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700178 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700179 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
180 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
181 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700182 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700183 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700184 return true;
185 }
186
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700187 @Test
188 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700189
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700190 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700191 FlowRule r2 = flowRule(2, 2);
192 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700193
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700194 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700195 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700196 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700197 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700198 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700199 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700200 r1, FlowEntryState.PENDING_ADD,
201 r2, FlowEntryState.PENDING_ADD,
202 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700203 }
204
205 @Test
206 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700207 FlowRule f1 = addFlowRule(1);
208 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700209 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700210 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700211
alshabib1c319ff2014-10-04 20:29:09 -0700212 FlowEntry fe1 = new DefaultFlowEntry(f1);
213 FlowEntry fe2 = new DefaultFlowEntry(f2);
214 FlowEntry fe3 = new DefaultFlowEntry(f3);
215 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700216 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
217 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700218
alshabib1c319ff2014-10-04 20:29:09 -0700219 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700220 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700221 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700222 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700223 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700224 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700225 f1, FlowEntryState.PENDING_REMOVE,
226 f2, FlowEntryState.PENDING_REMOVE,
227 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700228
alshabib1c319ff2014-10-04 20:29:09 -0700229 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700230 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700231 }
232
233 @Test
234 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700235 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700236 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700237 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700238 FlowEntry fe2 = new DefaultFlowEntry(f2);
239 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700240 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700241 fe1.setState(FlowEntryState.REMOVED);
242 providerService.flowRemoved(fe1);
alshabib3d643ec2014-10-22 18:33:00 -0700243 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
244 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700245
alshabib1c319ff2014-10-04 20:29:09 -0700246 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700247 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700248
alshabibba5ac482014-10-02 17:15:20 -0700249 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700250 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700251 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700252 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700253 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700254
alshabib1c319ff2014-10-04 20:29:09 -0700255 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700256 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700257 }
258
alshabibbb8b1282014-09-22 17:00:18 -0700259 @Test
260 public void flowMetrics() {
261 FlowRule f1 = flowRule(1, 1);
262 FlowRule f2 = flowRule(2, 2);
263 FlowRule f3 = flowRule(3, 3);
264
alshabibba5ac482014-10-02 17:15:20 -0700265 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700266
alshabib1c319ff2014-10-04 20:29:09 -0700267 FlowEntry fe1 = new DefaultFlowEntry(f1);
268 FlowEntry fe2 = new DefaultFlowEntry(f2);
269
270
271 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
272 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
273
274 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700275
276 assertTrue("Entries should be added.",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700277 validateState(ImmutableMap.of(
278 f1, FlowEntryState.ADDED,
279 f2, FlowEntryState.ADDED,
280 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700281
alshabib3d643ec2014-10-22 18:33:00 -0700282 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
283 RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700284 }
285
286 @Test
287 public void extraneousFlow() {
288 FlowRule f1 = flowRule(1, 1);
289 FlowRule f2 = flowRule(2, 2);
290 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700291 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700292
alshabib1c319ff2014-10-04 20:29:09 -0700293// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
294// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
295// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
296 FlowEntry fe1 = new DefaultFlowEntry(f1);
297 FlowEntry fe2 = new DefaultFlowEntry(f2);
298 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700299
alshabib1c319ff2014-10-04 20:29:09 -0700300
301 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700302
alshabib3d643ec2014-10-22 18:33:00 -0700303 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700304
305 }
306
307 /*
308 * Tests whether a rule that was marked for removal but no flowRemoved was received
309 * is indeed removed at the next stats update.
310 */
311 @Test
312 public void flowMissingRemove() {
313 FlowRule f1 = flowRule(1, 1);
314 FlowRule f2 = flowRule(2, 2);
315 FlowRule f3 = flowRule(3, 3);
316
alshabib1c319ff2014-10-04 20:29:09 -0700317// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
318// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
319
320 FlowEntry fe1 = new DefaultFlowEntry(f1);
321 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700322 mgr.applyFlowRules(f1, f2, f3);
323
324 mgr.removeFlowRules(f3);
325
alshabib1c319ff2014-10-04 20:29:09 -0700326 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700327
alshabib3d643ec2014-10-22 18:33:00 -0700328 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
329 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700330
331 }
332
333 @Test
334 public void getByAppId() {
335 FlowRule f1 = flowRule(1, 1);
336 FlowRule f2 = flowRule(2, 2);
337 mgr.applyFlowRules(f1, f2);
338
339 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700340 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700341 }
342
343 @Test
344 public void removeByAppId() {
345 FlowRule f1 = flowRule(1, 1);
346 FlowRule f2 = flowRule(2, 2);
347 mgr.applyFlowRules(f1, f2);
348
349
350 mgr.removeFlowRulesById(appId);
351
352 //only check that we are in pending remove. Events and actual remove state will
353 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700354 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700355 f1, FlowEntryState.PENDING_REMOVE,
356 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700357 }
358
alshabibcf369912014-10-13 14:16:42 -0700359 @Test
360 public void applyBatch() {
361 FlowRule f1 = flowRule(1, 1);
362 FlowRule f2 = flowRule(2, 2);
363
364
365 mgr.applyFlowRules(f1);
366
367 FlowEntry fe1 = new DefaultFlowEntry(f1);
368 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
369
370 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
371 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
372
373 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
374 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
375
376 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
377 Lists.newArrayList(fbe1, fbe2));
378 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
379 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700380 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700381 f1, FlowEntryState.PENDING_REMOVE,
382 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700383 CompletedBatchOperation completed = null;
384 try {
385 completed = future.get();
386 } catch (InterruptedException | ExecutionException e) {
387 fail("Unexpected exception: " + e);
388 }
389 if (!completed.isSuccess()) {
390 fail("Installation should be a success");
391 }
392
393 }
394
395 @Test
396 public void cancelBatch() {
397 FlowRule f1 = flowRule(1, 1);
398 FlowRule f2 = flowRule(2, 2);
399
400
401 mgr.applyFlowRules(f1);
402
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700403 assertTrue("Entries in wrong state",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700404 validateState(ImmutableMap.of(
405 f1, FlowEntryState.PENDING_ADD)));
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700406
alshabibcf369912014-10-13 14:16:42 -0700407 FlowEntry fe1 = new DefaultFlowEntry(f1);
408 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
409
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700410 assertTrue("Entries in wrong state",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700411 validateState(ImmutableMap.of(
412 f1, FlowEntryState.ADDED)));
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700413
414
alshabibcf369912014-10-13 14:16:42 -0700415 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
416 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
417
418 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
419 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
420
421 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
422 Lists.newArrayList(fbe1, fbe2));
423 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
424
425 future.cancel(true);
426
427 assertTrue(flowCount() == 2);
428
429 /*
430 * Rule f1 should be re-added to the list and therefore be in a pending add
431 * state.
432 */
433 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700434 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700435 f2, FlowEntryState.PENDING_REMOVE,
436 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700437
438
alshabibcf369912014-10-13 14:16:42 -0700439 }
440
441
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700442 private static class TestListener implements FlowRuleListener {
443 final List<FlowRuleEvent> events = new ArrayList<>();
444
445 @Override
446 public void event(FlowRuleEvent event) {
447 events.add(event);
448 }
449 }
450
451 private static class TestDeviceService implements DeviceService {
452
453 @Override
454 public int getDeviceCount() {
Madan Jampani6a456162014-10-24 11:36:17 -0700455 return 1;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700456 }
457
458 @Override
459 public Iterable<Device> getDevices() {
Madan Jampani6a456162014-10-24 11:36:17 -0700460 return Arrays.asList(DEV);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700461 }
462
463 @Override
464 public Device getDevice(DeviceId deviceId) {
465 return DEV;
466 }
467
468 @Override
469 public MastershipRole getRole(DeviceId deviceId) {
470 return null;
471 }
472
473 @Override
474 public List<Port> getPorts(DeviceId deviceId) {
475 return null;
476 }
477
478 @Override
479 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
480 return null;
481 }
482
483 @Override
484 public boolean isAvailable(DeviceId deviceId) {
485 return false;
486 }
487
488 @Override
489 public void addListener(DeviceListener listener) {
490 }
491
492 @Override
493 public void removeListener(DeviceListener listener) {
494 }
495
496 }
497
498 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
499
500 protected TestProvider(ProviderId id) {
501 super(PID);
502 }
503
504 @Override
505 public void applyFlowRule(FlowRule... flowRules) {
506 }
507
508 @Override
509 public void removeFlowRule(FlowRule... flowRules) {
510 }
511
alshabiba68eb962014-09-24 20:34:13 -0700512 @Override
513 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
514 }
515
alshabib902d41b2014-10-07 16:52:05 -0700516 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700517 public ListenableFuture<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700518 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700519 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700520 }
521
alshabibcf369912014-10-13 14:16:42 -0700522 private class TestInstallationFuture
Madan Jampani117aaae2014-10-23 10:04:05 -0700523 implements ListenableFuture<CompletedBatchOperation> {
alshabibcf369912014-10-13 14:16:42 -0700524
525 @Override
526 public boolean cancel(boolean mayInterruptIfRunning) {
527 return true;
528 }
529
530 @Override
531 public boolean isCancelled() {
532 return true;
533 }
534
535 @Override
536 public boolean isDone() {
537 return false;
538 }
539
540 @Override
541 public CompletedBatchOperation get()
542 throws InterruptedException, ExecutionException {
Madan Jampani117aaae2014-10-23 10:04:05 -0700543 return new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet());
alshabibcf369912014-10-13 14:16:42 -0700544 }
545
546 @Override
547 public CompletedBatchOperation get(long timeout, TimeUnit unit)
548 throws InterruptedException,
549 ExecutionException, TimeoutException {
550 return null;
551 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700552
553 @Override
554 public void addListener(Runnable task, Executor executor) {
555 // TODO: add stuff.
556 }
alshabibcf369912014-10-13 14:16:42 -0700557 }
alshabiba68eb962014-09-24 20:34:13 -0700558
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700559 }
560
561 private class TestSelector implements TrafficSelector {
562
563 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700564 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700565
566 public TestSelector(int val) {
567 testval = val;
568 }
569
570 @Override
alshabibba5ac482014-10-02 17:15:20 -0700571 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700572 return null;
573 }
574
575 @Override
Jonathan Hart936c49d2014-10-23 16:38:59 -0700576 public Criterion getCriterion(
577 org.onlab.onos.net.flow.criteria.Criterion.Type type) {
578 return null;
579 }
580
581 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700582 public int hashCode() {
583 return testval;
584 }
585
586 @Override
587 public boolean equals(Object o) {
588 if (o instanceof TestSelector) {
589 return this.testval == ((TestSelector) o).testval;
590 }
591 return false;
592 }
Jonathan Hart936c49d2014-10-23 16:38:59 -0700593
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700594 }
595
596 private class TestTreatment implements TrafficTreatment {
597
598 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700599 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700600
601 public TestTreatment(int val) {
602 testval = val;
603 }
604
605 @Override
606 public List<Instruction> instructions() {
607 return null;
608 }
609
610 @Override
611 public int hashCode() {
612 return testval;
613 }
614
615 @Override
616 public boolean equals(Object o) {
617 if (o instanceof TestTreatment) {
618 return this.testval == ((TestTreatment) o).testval;
619 }
620 return false;
621 }
622
623 }
624
alshabib92c65ad2014-10-08 21:56:05 -0700625 public class TestApplicationId extends DefaultApplicationId {
626
627 public TestApplicationId(short id, String name) {
628 super(id, name);
629 }
630 }
631
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700632}