blob: 472416ae2f77162072c39180a0351ca3df2adb56 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07002
alshabibcf369912014-10-13 14:16:42 -07003import static java.util.Collections.EMPTY_LIST;
4import static org.junit.Assert.*;
alshabib97044902014-09-18 14:52:16 -07005import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
6import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
alshabib219ebaa2014-09-22 15:41:24 -07007import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07008
9import java.util.ArrayList;
alshabibba5ac482014-10-02 17:15:20 -070010import java.util.Collections;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070011import java.util.HashMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070012import java.util.List;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070013import java.util.Map;
alshabibba5ac482014-10-02 17:15:20 -070014import java.util.Set;
alshabibcf369912014-10-13 14:16:42 -070015import java.util.concurrent.ExecutionException;
alshabib902d41b2014-10-07 16:52:05 -070016import java.util.concurrent.Future;
alshabibcf369912014-10-13 14:16:42 -070017import java.util.concurrent.TimeUnit;
18import java.util.concurrent.TimeoutException;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070019
20import org.junit.After;
21import org.junit.Before;
22import org.junit.Test;
alshabiba68eb962014-09-24 20:34:13 -070023import org.onlab.onos.ApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070024import org.onlab.onos.event.impl.TestEventDispatcher;
alshabib92c65ad2014-10-08 21:56:05 -070025import org.onlab.onos.impl.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070026import org.onlab.onos.net.DefaultDevice;
27import org.onlab.onos.net.Device;
28import org.onlab.onos.net.Device.Type;
29import org.onlab.onos.net.DeviceId;
30import org.onlab.onos.net.MastershipRole;
31import org.onlab.onos.net.Port;
32import org.onlab.onos.net.PortNumber;
33import org.onlab.onos.net.device.DeviceListener;
34import org.onlab.onos.net.device.DeviceService;
alshabib193525b2014-10-08 18:58:03 -070035import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070036import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070037import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070038import org.onlab.onos.net.flow.FlowEntry;
39import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070040import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070041import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070042import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070043import org.onlab.onos.net.flow.FlowRuleEvent;
44import org.onlab.onos.net.flow.FlowRuleListener;
45import org.onlab.onos.net.flow.FlowRuleProvider;
46import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
47import org.onlab.onos.net.flow.FlowRuleProviderService;
48import org.onlab.onos.net.flow.FlowRuleService;
49import org.onlab.onos.net.flow.TrafficSelector;
50import org.onlab.onos.net.flow.TrafficTreatment;
51import org.onlab.onos.net.flow.criteria.Criterion;
52import org.onlab.onos.net.flow.instructions.Instruction;
alshabib902d41b2014-10-07 16:52:05 -070053import org.onlab.onos.net.intent.BatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070054import org.onlab.onos.net.provider.AbstractProvider;
55import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070056import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070057
alshabibba5ac482014-10-02 17:15:20 -070058import com.google.common.collect.ImmutableList;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070059import com.google.common.collect.ImmutableMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070060import com.google.common.collect.Lists;
61import com.google.common.collect.Sets;
62
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
69
tomf6ab2152014-09-18 12:08:29 -070070 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070071 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070072 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070073 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070074 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070075
tom202175a2014-09-19 19:00:11 -070076 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070077
78 protected FlowRuleService service;
79 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070080 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070081 protected TestProvider provider;
82 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070083 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070084
85 @Before
86 public void setUp() {
tom202175a2014-09-19 19:00:11 -070087 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070088 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070089 mgr.eventDispatcher = new TestEventDispatcher();
90 mgr.deviceService = new TestDeviceService();
91 service = mgr;
92 registry = mgr;
93
94 mgr.activate();
95 mgr.addListener(listener);
96 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -070097 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -070098 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070099 assertTrue("provider should be registered",
100 registry.getProviders().contains(provider.id()));
101 }
102
103 @After
104 public void tearDown() {
105 registry.unregister(provider);
106 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700107 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700108 service.removeListener(listener);
109 mgr.deactivate();
110 mgr.eventDispatcher = null;
111 mgr.deviceService = null;
112 }
113
114 private FlowRule flowRule(int tsval, int trval) {
115 TestSelector ts = new TestSelector(tsval);
116 TestTreatment tr = new TestTreatment(trval);
alshabiba0e04982014-10-03 13:03:19 -0700117 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700118 }
119
alshabibbb8b1282014-09-22 17:00:18 -0700120
121 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700122 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700123 service.applyFlowRules(rule);
124
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700125 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700126 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700127 }
128
129 private void validateEvents(FlowRuleEvent.Type ... events) {
130 if (events == null) {
131 assertTrue("events generated", listener.events.isEmpty());
132 }
133
134 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700135 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700136 for (FlowRuleEvent e : listener.events) {
137 assertTrue("unexpected event", e.type().equals(events[i]));
138 i++;
139 }
140
141 assertEquals("mispredicted number of events",
142 events.length, listener.events.size());
143
144 listener.events.clear();
145 }
146
147 private int flowCount() {
148 return Sets.newHashSet(service.getFlowEntries(DID)).size();
149 }
150 @Test
151 public void getFlowEntries() {
152 assertTrue("store should be empty",
153 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));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700162 validateEvents(RULE_ADDED, RULE_ADDED);
163
164 addFlowRule(1);
165 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700166
alshabib1c319ff2014-10-04 20:29:09 -0700167 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700168 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700169 }
170
alshabibbb8b1282014-09-22 17:00:18 -0700171
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700172 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700173 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700174 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
175 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700176 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700177 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700178 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
179 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
180 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700181 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700182 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700183 return true;
184 }
185
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700186 @Test
187 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700188
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700189 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700190 FlowRule r2 = flowRule(2, 2);
191 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700192
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700193 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700194 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700195 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700196 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700197 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700198 validateState(ImmutableMap.of(
199 r1, FlowEntryState.PENDING_ADD,
200 r2, FlowEntryState.PENDING_ADD,
201 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700202 }
203
204 @Test
205 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700206 FlowRule f1 = addFlowRule(1);
207 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700208 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700209 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700210
alshabib1c319ff2014-10-04 20:29:09 -0700211 FlowEntry fe1 = new DefaultFlowEntry(f1);
212 FlowEntry fe2 = new DefaultFlowEntry(f2);
213 FlowEntry fe3 = new DefaultFlowEntry(f3);
214 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700215 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
216
alshabib1c319ff2014-10-04 20:29:09 -0700217 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700218 //removing from north, so no events generated
219 validateEvents();
alshabib219ebaa2014-09-22 15:41:24 -0700220 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700221 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700222 validateState(ImmutableMap.of(
223 f1, FlowEntryState.PENDING_REMOVE,
224 f2, FlowEntryState.PENDING_REMOVE,
225 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700226
alshabib1c319ff2014-10-04 20:29:09 -0700227 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700228 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700229 }
230
231 @Test
232 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700233 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700234 FlowRule f2 = addFlowRule(2);
alshabib1c319ff2014-10-04 20:29:09 -0700235 FlowEntry fe1 = new DefaultFlowEntry(f1);
236 FlowEntry fe2 = new DefaultFlowEntry(f2);
237 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700238 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700239 fe1.setState(FlowEntryState.REMOVED);
240 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700241 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
242
alshabib1c319ff2014-10-04 20:29:09 -0700243 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700244 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700245
alshabibba5ac482014-10-02 17:15:20 -0700246 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700247 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700248 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700249 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700250 validateEvents(RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700251
alshabib1c319ff2014-10-04 20:29:09 -0700252 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700253 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700254 }
255
alshabibbb8b1282014-09-22 17:00:18 -0700256 @Test
257 public void flowMetrics() {
258 FlowRule f1 = flowRule(1, 1);
259 FlowRule f2 = flowRule(2, 2);
260 FlowRule f3 = flowRule(3, 3);
261
alshabibba5ac482014-10-02 17:15:20 -0700262 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700263
alshabib1c319ff2014-10-04 20:29:09 -0700264 FlowEntry fe1 = new DefaultFlowEntry(f1);
265 FlowEntry fe2 = new DefaultFlowEntry(f2);
266
267
268 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
269 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
270
271 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700272
273 assertTrue("Entries should be added.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700274 validateState(ImmutableMap.of(
275 f1, FlowEntryState.ADDED,
276 f2, FlowEntryState.ADDED,
277 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700278
alshabibba5ac482014-10-02 17:15:20 -0700279 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700280 }
281
282 @Test
283 public void extraneousFlow() {
284 FlowRule f1 = flowRule(1, 1);
285 FlowRule f2 = flowRule(2, 2);
286 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700287 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700288
alshabib1c319ff2014-10-04 20:29:09 -0700289// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
290// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
291// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
292 FlowEntry fe1 = new DefaultFlowEntry(f1);
293 FlowEntry fe2 = new DefaultFlowEntry(f2);
294 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700295
alshabib1c319ff2014-10-04 20:29:09 -0700296
297 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700298
alshabibba5ac482014-10-02 17:15:20 -0700299 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700300
301 }
302
303 /*
304 * Tests whether a rule that was marked for removal but no flowRemoved was received
305 * is indeed removed at the next stats update.
306 */
307 @Test
308 public void flowMissingRemove() {
309 FlowRule f1 = flowRule(1, 1);
310 FlowRule f2 = flowRule(2, 2);
311 FlowRule f3 = flowRule(3, 3);
312
alshabib1c319ff2014-10-04 20:29:09 -0700313// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
314// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
315
316 FlowEntry fe1 = new DefaultFlowEntry(f1);
317 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700318 mgr.applyFlowRules(f1, f2, f3);
319
320 mgr.removeFlowRules(f3);
321
alshabib1c319ff2014-10-04 20:29:09 -0700322 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700323
alshabibba5ac482014-10-02 17:15:20 -0700324 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700325
326 }
327
328 @Test
329 public void getByAppId() {
330 FlowRule f1 = flowRule(1, 1);
331 FlowRule f2 = flowRule(2, 2);
332 mgr.applyFlowRules(f1, f2);
333
334 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700335 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700336 }
337
338 @Test
339 public void removeByAppId() {
340 FlowRule f1 = flowRule(1, 1);
341 FlowRule f2 = flowRule(2, 2);
342 mgr.applyFlowRules(f1, f2);
343
344
345 mgr.removeFlowRulesById(appId);
346
347 //only check that we are in pending remove. Events and actual remove state will
348 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700349 validateState(ImmutableMap.of(
350 f1, FlowEntryState.PENDING_REMOVE,
351 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700352 }
353
alshabibcf369912014-10-13 14:16:42 -0700354 @Test
355 public void applyBatch() {
356 FlowRule f1 = flowRule(1, 1);
357 FlowRule f2 = flowRule(2, 2);
358
359
360 mgr.applyFlowRules(f1);
361
362 FlowEntry fe1 = new DefaultFlowEntry(f1);
363 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
364
365 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
366 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
367
368 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
369 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
370
371 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
372 Lists.newArrayList(fbe1, fbe2));
373 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
374 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700375 validateState(ImmutableMap.of(
376 f1, FlowEntryState.PENDING_REMOVE,
377 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700378 CompletedBatchOperation completed = null;
379 try {
380 completed = future.get();
381 } catch (InterruptedException | ExecutionException e) {
382 fail("Unexpected exception: " + e);
383 }
384 if (!completed.isSuccess()) {
385 fail("Installation should be a success");
386 }
387
388 }
389
390 @Test
391 public void cancelBatch() {
392 FlowRule f1 = flowRule(1, 1);
393 FlowRule f2 = flowRule(2, 2);
394
395
396 mgr.applyFlowRules(f1);
397
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700398 assertTrue("Entries in wrong state",
399 validateState(ImmutableMap.of(
400 f1, FlowEntryState.PENDING_ADD)));
401
alshabibcf369912014-10-13 14:16:42 -0700402 FlowEntry fe1 = new DefaultFlowEntry(f1);
403 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
404
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700405 assertTrue("Entries in wrong state",
406 validateState(ImmutableMap.of(
407 f1, FlowEntryState.ADDED)));
408
409
alshabibcf369912014-10-13 14:16:42 -0700410 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
411 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
412
413 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
414 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
415
416 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
417 Lists.newArrayList(fbe1, fbe2));
418 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
419
420 future.cancel(true);
421
422 assertTrue(flowCount() == 2);
423
424 /*
425 * Rule f1 should be re-added to the list and therefore be in a pending add
426 * state.
427 */
428 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700429 validateState(ImmutableMap.of(
430 f2, FlowEntryState.PENDING_REMOVE,
431 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700432
433
alshabibcf369912014-10-13 14:16:42 -0700434 }
435
436
437
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700438 private static class TestListener implements FlowRuleListener {
439 final List<FlowRuleEvent> events = new ArrayList<>();
440
441 @Override
442 public void event(FlowRuleEvent event) {
443 events.add(event);
444 }
445 }
446
447 private static class TestDeviceService implements DeviceService {
448
449 @Override
450 public int getDeviceCount() {
451 return 0;
452 }
453
454 @Override
455 public Iterable<Device> getDevices() {
456 return null;
457 }
458
459 @Override
460 public Device getDevice(DeviceId deviceId) {
461 return DEV;
462 }
463
464 @Override
465 public MastershipRole getRole(DeviceId deviceId) {
466 return null;
467 }
468
469 @Override
470 public List<Port> getPorts(DeviceId deviceId) {
471 return null;
472 }
473
474 @Override
475 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
476 return null;
477 }
478
479 @Override
480 public boolean isAvailable(DeviceId deviceId) {
481 return false;
482 }
483
484 @Override
485 public void addListener(DeviceListener listener) {
486 }
487
488 @Override
489 public void removeListener(DeviceListener listener) {
490 }
491
492 }
493
494 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
495
496 protected TestProvider(ProviderId id) {
497 super(PID);
498 }
499
500 @Override
501 public void applyFlowRule(FlowRule... flowRules) {
502 }
503
504 @Override
505 public void removeFlowRule(FlowRule... flowRules) {
506 }
507
alshabiba68eb962014-09-24 20:34:13 -0700508 @Override
509 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
510 }
511
alshabib902d41b2014-10-07 16:52:05 -0700512 @Override
alshabib193525b2014-10-08 18:58:03 -0700513 public Future<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700514 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700515 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700516 }
517
alshabibcf369912014-10-13 14:16:42 -0700518 private class TestInstallationFuture
519 implements Future<CompletedBatchOperation> {
520
521 @Override
522 public boolean cancel(boolean mayInterruptIfRunning) {
523 return true;
524 }
525
526 @Override
527 public boolean isCancelled() {
528 return true;
529 }
530
531 @Override
532 public boolean isDone() {
533 return false;
534 }
535
536 @Override
537 public CompletedBatchOperation get()
538 throws InterruptedException, ExecutionException {
539 return new CompletedBatchOperation(true, EMPTY_LIST);
540 }
541
542 @Override
543 public CompletedBatchOperation get(long timeout, TimeUnit unit)
544 throws InterruptedException,
545 ExecutionException, TimeoutException {
546 return null;
547 }
548 }
alshabiba68eb962014-09-24 20:34:13 -0700549
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700550 }
551
552 private class TestSelector implements TrafficSelector {
553
554 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700555 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700556
557 public TestSelector(int val) {
558 testval = val;
559 }
560
561 @Override
alshabibba5ac482014-10-02 17:15:20 -0700562 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700563 return null;
564 }
565
566 @Override
567 public int hashCode() {
568 return testval;
569 }
570
571 @Override
572 public boolean equals(Object o) {
573 if (o instanceof TestSelector) {
574 return this.testval == ((TestSelector) o).testval;
575 }
576 return false;
577 }
578 }
579
580 private class TestTreatment implements TrafficTreatment {
581
582 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700583 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700584
585 public TestTreatment(int val) {
586 testval = val;
587 }
588
589 @Override
590 public List<Instruction> instructions() {
591 return null;
592 }
593
594 @Override
595 public int hashCode() {
596 return testval;
597 }
598
599 @Override
600 public boolean equals(Object o) {
601 if (o instanceof TestTreatment) {
602 return this.testval == ((TestTreatment) o).testval;
603 }
604 return false;
605 }
606
607 }
608
alshabib92c65ad2014-10-08 21:56:05 -0700609 public class TestApplicationId extends DefaultApplicationId {
610
611 public TestApplicationId(short id, String name) {
612 super(id, name);
613 }
614 }
615
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700616}