blob: 59b2963d8d305804586452d2798410db3cf01406 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07002
Jonathan Hartbc4a7932014-10-21 11:46:00 -07003import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertFalse;
5import static org.junit.Assert.assertNotNull;
6import static org.junit.Assert.assertTrue;
7import static org.junit.Assert.fail;
alshabib97044902014-09-18 14:52:16 -07008import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
9import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
alshabib219ebaa2014-09-22 15:41:24 -070010import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070011
12import java.util.ArrayList;
alshabibba5ac482014-10-02 17:15:20 -070013import java.util.Collections;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070014import java.util.HashMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070015import java.util.List;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070016import java.util.Map;
alshabibba5ac482014-10-02 17:15:20 -070017import java.util.Set;
alshabibcf369912014-10-13 14:16:42 -070018import java.util.concurrent.ExecutionException;
Madan Jampani117aaae2014-10-23 10:04:05 -070019import java.util.concurrent.Executor;
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;
Madan Jampani117aaae2014-10-23 10:04:05 -070067import com.google.common.util.concurrent.ListenableFuture;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070068
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070069/**
70 * Test codifying the flow rule service & flow rule provider service contracts.
71 */
tom202175a2014-09-19 19:00:11 -070072public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070073
alshabib92c65ad2014-10-08 21:56:05 -070074
75
tomf6ab2152014-09-18 12:08:29 -070076 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070077 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070078 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070079 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070080 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070081
tom202175a2014-09-19 19:00:11 -070082 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070083
84 protected FlowRuleService service;
85 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070086 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070087 protected TestProvider provider;
88 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070089 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070090
91 @Before
92 public void setUp() {
tom202175a2014-09-19 19:00:11 -070093 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070094 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070095 mgr.eventDispatcher = new TestEventDispatcher();
96 mgr.deviceService = new TestDeviceService();
97 service = mgr;
98 registry = mgr;
99
100 mgr.activate();
101 mgr.addListener(listener);
102 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700103 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -0700104 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700105 assertTrue("provider should be registered",
106 registry.getProviders().contains(provider.id()));
107 }
108
109 @After
110 public void tearDown() {
111 registry.unregister(provider);
112 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700113 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700114 service.removeListener(listener);
115 mgr.deactivate();
116 mgr.eventDispatcher = null;
117 mgr.deviceService = null;
118 }
119
120 private FlowRule flowRule(int tsval, int trval) {
121 TestSelector ts = new TestSelector(tsval);
122 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700123 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700124 }
125
alshabibbb8b1282014-09-22 17:00:18 -0700126
127 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700128 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700129 service.applyFlowRules(rule);
130
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700131 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700132 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700133 }
134
135 private void validateEvents(FlowRuleEvent.Type ... events) {
136 if (events == null) {
137 assertTrue("events generated", listener.events.isEmpty());
138 }
139
140 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700141 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700142 for (FlowRuleEvent e : listener.events) {
143 assertTrue("unexpected event", e.type().equals(events[i]));
144 i++;
145 }
146
147 assertEquals("mispredicted number of events",
148 events.length, listener.events.size());
149
150 listener.events.clear();
151 }
152
153 private int flowCount() {
154 return Sets.newHashSet(service.getFlowEntries(DID)).size();
155 }
156 @Test
157 public void getFlowEntries() {
158 assertTrue("store should be empty",
159 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700160 FlowRule f1 = addFlowRule(1);
161 FlowRule f2 = addFlowRule(2);
162
alshabib1c319ff2014-10-04 20:29:09 -0700163 FlowEntry fe1 = new DefaultFlowEntry(f1);
164 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700165 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700166
alshabib1c319ff2014-10-04 20:29:09 -0700167 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700168 validateEvents(RULE_ADDED, RULE_ADDED);
169
170 addFlowRule(1);
171 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700172
alshabib1c319ff2014-10-04 20:29:09 -0700173 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700174 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700175 }
176
alshabibbb8b1282014-09-22 17:00:18 -0700177
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700178 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700179 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700180 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
181 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700182 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700183 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700184 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
185 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
186 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700187 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700188 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700189 return true;
190 }
191
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700192 @Test
193 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700194
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700195 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700196 FlowRule r2 = flowRule(2, 2);
197 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700198
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700199 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700200 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700201 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700202 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700203 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700204 validateState(ImmutableMap.of(
205 r1, FlowEntryState.PENDING_ADD,
206 r2, FlowEntryState.PENDING_ADD,
207 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700208 }
209
210 @Test
211 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700212 FlowRule f1 = addFlowRule(1);
213 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700214 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700215 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700216
alshabib1c319ff2014-10-04 20:29:09 -0700217 FlowEntry fe1 = new DefaultFlowEntry(f1);
218 FlowEntry fe2 = new DefaultFlowEntry(f2);
219 FlowEntry fe3 = new DefaultFlowEntry(f3);
220 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700221 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
222
alshabib1c319ff2014-10-04 20:29:09 -0700223 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700224 //removing from north, so no events generated
225 validateEvents();
alshabib219ebaa2014-09-22 15:41:24 -0700226 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700227 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700228 validateState(ImmutableMap.of(
229 f1, FlowEntryState.PENDING_REMOVE,
230 f2, FlowEntryState.PENDING_REMOVE,
231 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700232
alshabib1c319ff2014-10-04 20:29:09 -0700233 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700234 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700235 }
236
237 @Test
238 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700239 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700240 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700241 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700242 FlowEntry fe2 = new DefaultFlowEntry(f2);
243 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700244 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700245 fe1.setState(FlowEntryState.REMOVED);
246 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700247 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
248
alshabib1c319ff2014-10-04 20:29:09 -0700249 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700250 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700251
alshabibba5ac482014-10-02 17:15:20 -0700252 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700253 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700254 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700255 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700256 validateEvents(RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700257
alshabib1c319ff2014-10-04 20:29:09 -0700258 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700259 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700260 }
261
alshabibbb8b1282014-09-22 17:00:18 -0700262 @Test
263 public void flowMetrics() {
264 FlowRule f1 = flowRule(1, 1);
265 FlowRule f2 = flowRule(2, 2);
266 FlowRule f3 = flowRule(3, 3);
267
alshabibba5ac482014-10-02 17:15:20 -0700268 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700269
alshabib1c319ff2014-10-04 20:29:09 -0700270 FlowEntry fe1 = new DefaultFlowEntry(f1);
271 FlowEntry fe2 = new DefaultFlowEntry(f2);
272
273
274 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
275 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
276
277 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700278
279 assertTrue("Entries should be added.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700280 validateState(ImmutableMap.of(
281 f1, FlowEntryState.ADDED,
282 f2, FlowEntryState.ADDED,
283 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700284
alshabibba5ac482014-10-02 17:15:20 -0700285 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700286 }
287
288 @Test
289 public void extraneousFlow() {
290 FlowRule f1 = flowRule(1, 1);
291 FlowRule f2 = flowRule(2, 2);
292 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700293 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700294
alshabib1c319ff2014-10-04 20:29:09 -0700295// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
296// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
297// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
298 FlowEntry fe1 = new DefaultFlowEntry(f1);
299 FlowEntry fe2 = new DefaultFlowEntry(f2);
300 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700301
alshabib1c319ff2014-10-04 20:29:09 -0700302
303 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700304
alshabibba5ac482014-10-02 17:15:20 -0700305 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700306
307 }
308
309 /*
310 * Tests whether a rule that was marked for removal but no flowRemoved was received
311 * is indeed removed at the next stats update.
312 */
313 @Test
314 public void flowMissingRemove() {
315 FlowRule f1 = flowRule(1, 1);
316 FlowRule f2 = flowRule(2, 2);
317 FlowRule f3 = flowRule(3, 3);
318
alshabib1c319ff2014-10-04 20:29:09 -0700319// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
320// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
321
322 FlowEntry fe1 = new DefaultFlowEntry(f1);
323 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700324 mgr.applyFlowRules(f1, f2, f3);
325
326 mgr.removeFlowRules(f3);
327
alshabib1c319ff2014-10-04 20:29:09 -0700328 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700329
alshabibba5ac482014-10-02 17:15:20 -0700330 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700331
332 }
333
334 @Test
335 public void getByAppId() {
336 FlowRule f1 = flowRule(1, 1);
337 FlowRule f2 = flowRule(2, 2);
338 mgr.applyFlowRules(f1, f2);
339
340 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700341 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700342 }
343
344 @Test
345 public void removeByAppId() {
346 FlowRule f1 = flowRule(1, 1);
347 FlowRule f2 = flowRule(2, 2);
348 mgr.applyFlowRules(f1, f2);
349
350
351 mgr.removeFlowRulesById(appId);
352
353 //only check that we are in pending remove. Events and actual remove state will
354 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700355 validateState(ImmutableMap.of(
356 f1, FlowEntryState.PENDING_REMOVE,
357 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700358 }
359
alshabibcf369912014-10-13 14:16:42 -0700360 @Test
361 public void applyBatch() {
362 FlowRule f1 = flowRule(1, 1);
363 FlowRule f2 = flowRule(2, 2);
364
365
366 mgr.applyFlowRules(f1);
367
368 FlowEntry fe1 = new DefaultFlowEntry(f1);
369 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
370
371 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
372 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
373
374 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
375 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
376
377 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
378 Lists.newArrayList(fbe1, fbe2));
379 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
380 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700381 validateState(ImmutableMap.of(
382 f1, FlowEntryState.PENDING_REMOVE,
383 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700384 CompletedBatchOperation completed = null;
385 try {
386 completed = future.get();
387 } catch (InterruptedException | ExecutionException e) {
388 fail("Unexpected exception: " + e);
389 }
390 if (!completed.isSuccess()) {
391 fail("Installation should be a success");
392 }
393
394 }
395
396 @Test
397 public void cancelBatch() {
398 FlowRule f1 = flowRule(1, 1);
399 FlowRule f2 = flowRule(2, 2);
400
401
402 mgr.applyFlowRules(f1);
403
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700404 assertTrue("Entries in wrong state",
405 validateState(ImmutableMap.of(
406 f1, FlowEntryState.PENDING_ADD)));
407
alshabibcf369912014-10-13 14:16:42 -0700408 FlowEntry fe1 = new DefaultFlowEntry(f1);
409 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
410
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700411 assertTrue("Entries in wrong state",
412 validateState(ImmutableMap.of(
413 f1, FlowEntryState.ADDED)));
414
415
alshabibcf369912014-10-13 14:16:42 -0700416 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
417 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
418
419 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
420 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
421
422 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
423 Lists.newArrayList(fbe1, fbe2));
424 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
425
426 future.cancel(true);
427
428 assertTrue(flowCount() == 2);
429
430 /*
431 * Rule f1 should be re-added to the list and therefore be in a pending add
432 * state.
433 */
434 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700435 validateState(ImmutableMap.of(
436 f2, FlowEntryState.PENDING_REMOVE,
437 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700438
439
alshabibcf369912014-10-13 14:16:42 -0700440 }
441
442
443
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700444 private static class TestListener implements FlowRuleListener {
445 final List<FlowRuleEvent> events = new ArrayList<>();
446
447 @Override
448 public void event(FlowRuleEvent event) {
449 events.add(event);
450 }
451 }
452
453 private static class TestDeviceService implements DeviceService {
454
455 @Override
456 public int getDeviceCount() {
457 return 0;
458 }
459
460 @Override
461 public Iterable<Device> getDevices() {
462 return null;
463 }
464
465 @Override
466 public Device getDevice(DeviceId deviceId) {
467 return DEV;
468 }
469
470 @Override
471 public MastershipRole getRole(DeviceId deviceId) {
472 return null;
473 }
474
475 @Override
476 public List<Port> getPorts(DeviceId deviceId) {
477 return null;
478 }
479
480 @Override
481 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
482 return null;
483 }
484
485 @Override
486 public boolean isAvailable(DeviceId deviceId) {
487 return false;
488 }
489
490 @Override
491 public void addListener(DeviceListener listener) {
492 }
493
494 @Override
495 public void removeListener(DeviceListener listener) {
496 }
497
498 }
499
500 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
501
502 protected TestProvider(ProviderId id) {
503 super(PID);
504 }
505
506 @Override
507 public void applyFlowRule(FlowRule... flowRules) {
508 }
509
510 @Override
511 public void removeFlowRule(FlowRule... flowRules) {
512 }
513
alshabiba68eb962014-09-24 20:34:13 -0700514 @Override
515 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
516 }
517
alshabib902d41b2014-10-07 16:52:05 -0700518 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700519 public ListenableFuture<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700520 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700521 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700522 }
523
alshabibcf369912014-10-13 14:16:42 -0700524 private class TestInstallationFuture
Madan Jampani117aaae2014-10-23 10:04:05 -0700525 implements ListenableFuture<CompletedBatchOperation> {
alshabibcf369912014-10-13 14:16:42 -0700526
527 @Override
528 public boolean cancel(boolean mayInterruptIfRunning) {
529 return true;
530 }
531
532 @Override
533 public boolean isCancelled() {
534 return true;
535 }
536
537 @Override
538 public boolean isDone() {
539 return false;
540 }
541
542 @Override
543 public CompletedBatchOperation get()
544 throws InterruptedException, ExecutionException {
Madan Jampani117aaae2014-10-23 10:04:05 -0700545 return new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet());
alshabibcf369912014-10-13 14:16:42 -0700546 }
547
548 @Override
549 public CompletedBatchOperation get(long timeout, TimeUnit unit)
550 throws InterruptedException,
551 ExecutionException, TimeoutException {
552 return null;
553 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700554
555 @Override
556 public void addListener(Runnable task, Executor executor) {
557 // TODO: add stuff.
558 }
alshabibcf369912014-10-13 14:16:42 -0700559 }
alshabiba68eb962014-09-24 20:34:13 -0700560
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700561 }
562
563 private class TestSelector implements TrafficSelector {
564
565 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700566 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700567
568 public TestSelector(int val) {
569 testval = val;
570 }
571
572 @Override
alshabibba5ac482014-10-02 17:15:20 -0700573 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700574 return null;
575 }
576
577 @Override
578 public int hashCode() {
579 return testval;
580 }
581
582 @Override
583 public boolean equals(Object o) {
584 if (o instanceof TestSelector) {
585 return this.testval == ((TestSelector) o).testval;
586 }
587 return false;
588 }
589 }
590
591 private class TestTreatment implements TrafficTreatment {
592
593 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700594 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700595
596 public TestTreatment(int val) {
597 testval = val;
598 }
599
600 @Override
601 public List<Instruction> instructions() {
602 return null;
603 }
604
605 @Override
606 public int hashCode() {
607 return testval;
608 }
609
610 @Override
611 public boolean equals(Object o) {
612 if (o instanceof TestTreatment) {
613 return this.testval == ((TestTreatment) o).testval;
614 }
615 return false;
616 }
617
618 }
619
alshabib92c65ad2014-10-08 21:56:05 -0700620 public class TestApplicationId extends DefaultApplicationId {
621
622 public TestApplicationId(short id, String name) {
623 super(id, name);
624 }
625 }
626
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700627}