blob: ca7cc077f0fc4728d32b954be4220a4f1bcabbba [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;
Jonathan Hartbc4a7932014-10-21 11:46:00 -07004import static org.junit.Assert.assertEquals;
5import static org.junit.Assert.assertFalse;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertTrue;
8import static org.junit.Assert.fail;
alshabib97044902014-09-18 14:52:16 -07009import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
10import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
alshabib219ebaa2014-09-22 15:41:24 -070011import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070012
13import java.util.ArrayList;
alshabibba5ac482014-10-02 17:15:20 -070014import java.util.Collections;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070015import java.util.HashMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070016import java.util.List;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070017import java.util.Map;
alshabibba5ac482014-10-02 17:15:20 -070018import java.util.Set;
alshabibcf369912014-10-13 14:16:42 -070019import java.util.concurrent.ExecutionException;
alshabib902d41b2014-10-07 16:52:05 -070020import java.util.concurrent.Future;
alshabibcf369912014-10-13 14:16:42 -070021import java.util.concurrent.TimeUnit;
22import java.util.concurrent.TimeoutException;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070023
24import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
alshabiba68eb962014-09-24 20:34:13 -070027import org.onlab.onos.ApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070028import org.onlab.onos.event.impl.TestEventDispatcher;
alshabib92c65ad2014-10-08 21:56:05 -070029import org.onlab.onos.impl.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070030import 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;
38import org.onlab.onos.net.device.DeviceService;
alshabib193525b2014-10-08 18:58:03 -070039import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070040import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070041import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070042import org.onlab.onos.net.flow.FlowEntry;
43import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070044import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070045import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070046import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070047import org.onlab.onos.net.flow.FlowRuleEvent;
48import org.onlab.onos.net.flow.FlowRuleListener;
49import org.onlab.onos.net.flow.FlowRuleProvider;
50import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
51import org.onlab.onos.net.flow.FlowRuleProviderService;
52import org.onlab.onos.net.flow.FlowRuleService;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070053import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070054import org.onlab.onos.net.flow.TrafficSelector;
55import org.onlab.onos.net.flow.TrafficTreatment;
56import org.onlab.onos.net.flow.criteria.Criterion;
57import org.onlab.onos.net.flow.instructions.Instruction;
alshabib902d41b2014-10-07 16:52:05 -070058import org.onlab.onos.net.intent.BatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070059import 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
alshabibba5ac482014-10-02 17:15:20 -070063import com.google.common.collect.ImmutableList;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070064import com.google.common.collect.ImmutableMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070065import com.google.common.collect.Lists;
66import com.google.common.collect.Sets;
67
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070068/**
69 * Test codifying the flow rule service & flow rule provider service contracts.
70 */
tom202175a2014-09-19 19:00:11 -070071public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070072
alshabib92c65ad2014-10-08 21:56:05 -070073
74
tomf6ab2152014-09-18 12:08:29 -070075 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070076 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070077 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070078 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070079 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070080
tom202175a2014-09-19 19:00:11 -070081 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070082
83 protected FlowRuleService service;
84 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070085 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070086 protected TestProvider provider;
87 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070088 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070089
90 @Before
91 public void setUp() {
tom202175a2014-09-19 19:00:11 -070092 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070093 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070094 mgr.eventDispatcher = new TestEventDispatcher();
95 mgr.deviceService = new TestDeviceService();
96 service = mgr;
97 registry = mgr;
98
99 mgr.activate();
100 mgr.addListener(listener);
101 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700102 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -0700103 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700104 assertTrue("provider should be registered",
105 registry.getProviders().contains(provider.id()));
106 }
107
108 @After
109 public void tearDown() {
110 registry.unregister(provider);
111 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700112 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700113 service.removeListener(listener);
114 mgr.deactivate();
115 mgr.eventDispatcher = null;
116 mgr.deviceService = null;
117 }
118
119 private FlowRule flowRule(int tsval, int trval) {
120 TestSelector ts = new TestSelector(tsval);
121 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700122 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700123 }
124
alshabibbb8b1282014-09-22 17:00:18 -0700125
126 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700127 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700128 service.applyFlowRules(rule);
129
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700130 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700131 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700132 }
133
134 private void validateEvents(FlowRuleEvent.Type ... events) {
135 if (events == null) {
136 assertTrue("events generated", listener.events.isEmpty());
137 }
138
139 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700140 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700141 for (FlowRuleEvent e : listener.events) {
142 assertTrue("unexpected event", e.type().equals(events[i]));
143 i++;
144 }
145
146 assertEquals("mispredicted number of events",
147 events.length, listener.events.size());
148
149 listener.events.clear();
150 }
151
152 private int flowCount() {
153 return Sets.newHashSet(service.getFlowEntries(DID)).size();
154 }
155 @Test
156 public void getFlowEntries() {
157 assertTrue("store should be empty",
158 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700159 FlowRule f1 = addFlowRule(1);
160 FlowRule f2 = addFlowRule(2);
161
alshabib1c319ff2014-10-04 20:29:09 -0700162 FlowEntry fe1 = new DefaultFlowEntry(f1);
163 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700164 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700165
alshabib1c319ff2014-10-04 20:29:09 -0700166 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700167 validateEvents(RULE_ADDED, RULE_ADDED);
168
169 addFlowRule(1);
170 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700171
alshabib1c319ff2014-10-04 20:29:09 -0700172 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700173 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700174 }
175
alshabibbb8b1282014-09-22 17:00:18 -0700176
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700177 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700178 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700179 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
180 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700181 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700182 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700183 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
184 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
185 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700186 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700187 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700188 return true;
189 }
190
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700191 @Test
192 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700193
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700194 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700195 FlowRule r2 = flowRule(2, 2);
196 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700197
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700198 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700199 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700200 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700201 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700202 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700203 validateState(ImmutableMap.of(
204 r1, FlowEntryState.PENDING_ADD,
205 r2, FlowEntryState.PENDING_ADD,
206 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700207 }
208
209 @Test
210 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700211 FlowRule f1 = addFlowRule(1);
212 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700213 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700214 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700215
alshabib1c319ff2014-10-04 20:29:09 -0700216 FlowEntry fe1 = new DefaultFlowEntry(f1);
217 FlowEntry fe2 = new DefaultFlowEntry(f2);
218 FlowEntry fe3 = new DefaultFlowEntry(f3);
219 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700220 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
221
alshabib1c319ff2014-10-04 20:29:09 -0700222 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700223 //removing from north, so no events generated
224 validateEvents();
alshabib219ebaa2014-09-22 15:41:24 -0700225 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700226 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700227 validateState(ImmutableMap.of(
228 f1, FlowEntryState.PENDING_REMOVE,
229 f2, FlowEntryState.PENDING_REMOVE,
230 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700231
alshabib1c319ff2014-10-04 20:29:09 -0700232 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700233 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700234 }
235
236 @Test
237 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700238 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700239 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700240 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700241 FlowEntry fe2 = new DefaultFlowEntry(f2);
242 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700243 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700244 fe1.setState(FlowEntryState.REMOVED);
245 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700246 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
247
alshabib1c319ff2014-10-04 20:29:09 -0700248 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700249 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700250
alshabibba5ac482014-10-02 17:15:20 -0700251 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700252 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700253 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700254 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700255 validateEvents(RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700256
alshabib1c319ff2014-10-04 20:29:09 -0700257 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700258 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700259 }
260
alshabibbb8b1282014-09-22 17:00:18 -0700261 @Test
262 public void flowMetrics() {
263 FlowRule f1 = flowRule(1, 1);
264 FlowRule f2 = flowRule(2, 2);
265 FlowRule f3 = flowRule(3, 3);
266
alshabibba5ac482014-10-02 17:15:20 -0700267 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700268
alshabib1c319ff2014-10-04 20:29:09 -0700269 FlowEntry fe1 = new DefaultFlowEntry(f1);
270 FlowEntry fe2 = new DefaultFlowEntry(f2);
271
272
273 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
274 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
275
276 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700277
278 assertTrue("Entries should be added.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700279 validateState(ImmutableMap.of(
280 f1, FlowEntryState.ADDED,
281 f2, FlowEntryState.ADDED,
282 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700283
alshabibba5ac482014-10-02 17:15:20 -0700284 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700285 }
286
287 @Test
288 public void extraneousFlow() {
289 FlowRule f1 = flowRule(1, 1);
290 FlowRule f2 = flowRule(2, 2);
291 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700292 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700293
alshabib1c319ff2014-10-04 20:29:09 -0700294// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
295// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
296// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
297 FlowEntry fe1 = new DefaultFlowEntry(f1);
298 FlowEntry fe2 = new DefaultFlowEntry(f2);
299 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700300
alshabib1c319ff2014-10-04 20:29:09 -0700301
302 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700303
alshabibba5ac482014-10-02 17:15:20 -0700304 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700305
306 }
307
308 /*
309 * Tests whether a rule that was marked for removal but no flowRemoved was received
310 * is indeed removed at the next stats update.
311 */
312 @Test
313 public void flowMissingRemove() {
314 FlowRule f1 = flowRule(1, 1);
315 FlowRule f2 = flowRule(2, 2);
316 FlowRule f3 = flowRule(3, 3);
317
alshabib1c319ff2014-10-04 20:29:09 -0700318// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
319// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
320
321 FlowEntry fe1 = new DefaultFlowEntry(f1);
322 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700323 mgr.applyFlowRules(f1, f2, f3);
324
325 mgr.removeFlowRules(f3);
326
alshabib1c319ff2014-10-04 20:29:09 -0700327 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700328
alshabibba5ac482014-10-02 17:15:20 -0700329 validateEvents(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(
355 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(
381 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",
404 validateState(ImmutableMap.of(
405 f1, FlowEntryState.PENDING_ADD)));
406
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",
411 validateState(ImmutableMap.of(
412 f1, FlowEntryState.ADDED)));
413
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(
435 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
442
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700443 private static class TestListener implements FlowRuleListener {
444 final List<FlowRuleEvent> events = new ArrayList<>();
445
446 @Override
447 public void event(FlowRuleEvent event) {
448 events.add(event);
449 }
450 }
451
452 private static class TestDeviceService implements DeviceService {
453
454 @Override
455 public int getDeviceCount() {
456 return 0;
457 }
458
459 @Override
460 public Iterable<Device> getDevices() {
461 return null;
462 }
463
464 @Override
465 public Device getDevice(DeviceId deviceId) {
466 return DEV;
467 }
468
469 @Override
470 public MastershipRole getRole(DeviceId deviceId) {
471 return null;
472 }
473
474 @Override
475 public List<Port> getPorts(DeviceId deviceId) {
476 return null;
477 }
478
479 @Override
480 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
481 return null;
482 }
483
484 @Override
485 public boolean isAvailable(DeviceId deviceId) {
486 return false;
487 }
488
489 @Override
490 public void addListener(DeviceListener listener) {
491 }
492
493 @Override
494 public void removeListener(DeviceListener listener) {
495 }
496
497 }
498
499 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
500
501 protected TestProvider(ProviderId id) {
502 super(PID);
503 }
504
505 @Override
506 public void applyFlowRule(FlowRule... flowRules) {
507 }
508
509 @Override
510 public void removeFlowRule(FlowRule... flowRules) {
511 }
512
alshabiba68eb962014-09-24 20:34:13 -0700513 @Override
514 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
515 }
516
alshabib902d41b2014-10-07 16:52:05 -0700517 @Override
alshabib193525b2014-10-08 18:58:03 -0700518 public Future<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700519 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700520 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700521 }
522
alshabibcf369912014-10-13 14:16:42 -0700523 private class TestInstallationFuture
524 implements Future<CompletedBatchOperation> {
525
526 @Override
527 public boolean cancel(boolean mayInterruptIfRunning) {
528 return true;
529 }
530
531 @Override
532 public boolean isCancelled() {
533 return true;
534 }
535
536 @Override
537 public boolean isDone() {
538 return false;
539 }
540
541 @Override
542 public CompletedBatchOperation get()
543 throws InterruptedException, ExecutionException {
544 return new CompletedBatchOperation(true, EMPTY_LIST);
545 }
546
547 @Override
548 public CompletedBatchOperation get(long timeout, TimeUnit unit)
549 throws InterruptedException,
550 ExecutionException, TimeoutException {
551 return null;
552 }
553 }
alshabiba68eb962014-09-24 20:34:13 -0700554
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700555 }
556
557 private class TestSelector implements TrafficSelector {
558
559 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700560 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700561
562 public TestSelector(int val) {
563 testval = val;
564 }
565
566 @Override
alshabibba5ac482014-10-02 17:15:20 -0700567 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700568 return null;
569 }
570
571 @Override
572 public int hashCode() {
573 return testval;
574 }
575
576 @Override
577 public boolean equals(Object o) {
578 if (o instanceof TestSelector) {
579 return this.testval == ((TestSelector) o).testval;
580 }
581 return false;
582 }
583 }
584
585 private class TestTreatment implements TrafficTreatment {
586
587 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700588 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700589
590 public TestTreatment(int val) {
591 testval = val;
592 }
593
594 @Override
595 public List<Instruction> instructions() {
596 return null;
597 }
598
599 @Override
600 public int hashCode() {
601 return testval;
602 }
603
604 @Override
605 public boolean equals(Object o) {
606 if (o instanceof TestTreatment) {
607 return this.testval == ((TestTreatment) o).testval;
608 }
609 return false;
610 }
611
612 }
613
alshabib92c65ad2014-10-08 21:56:05 -0700614 public class TestApplicationId extends DefaultApplicationId {
615
616 public TestApplicationId(short id, String name) {
617 super(id, name);
618 }
619 }
620
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700621}