blob: dff740a1d4aa3fca9696bc4a361198e2a1e75ec8 [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;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070049import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070050import org.onlab.onos.net.flow.TrafficSelector;
51import org.onlab.onos.net.flow.TrafficTreatment;
52import org.onlab.onos.net.flow.criteria.Criterion;
53import org.onlab.onos.net.flow.instructions.Instruction;
alshabib902d41b2014-10-07 16:52:05 -070054import org.onlab.onos.net.intent.BatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070055import org.onlab.onos.net.provider.AbstractProvider;
56import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070057import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070058
alshabibba5ac482014-10-02 17:15:20 -070059import com.google.common.collect.ImmutableList;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070060import com.google.common.collect.ImmutableMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070061import com.google.common.collect.Lists;
62import com.google.common.collect.Sets;
63
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070064/**
65 * Test codifying the flow rule service & flow rule provider service contracts.
66 */
tom202175a2014-09-19 19:00:11 -070067public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070068
alshabib92c65ad2014-10-08 21:56:05 -070069
70
tomf6ab2152014-09-18 12:08:29 -070071 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070072 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070073 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070074 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070075 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070076
tom202175a2014-09-19 19:00:11 -070077 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070078
79 protected FlowRuleService service;
80 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070081 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070082 protected TestProvider provider;
83 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070084 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070085
86 @Before
87 public void setUp() {
tom202175a2014-09-19 19:00:11 -070088 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070089 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070090 mgr.eventDispatcher = new TestEventDispatcher();
91 mgr.deviceService = new TestDeviceService();
92 service = mgr;
93 registry = mgr;
94
95 mgr.activate();
96 mgr.addListener(listener);
97 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -070098 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -070099 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700100 assertTrue("provider should be registered",
101 registry.getProviders().contains(provider.id()));
102 }
103
104 @After
105 public void tearDown() {
106 registry.unregister(provider);
107 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700108 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700109 service.removeListener(listener);
110 mgr.deactivate();
111 mgr.eventDispatcher = null;
112 mgr.deviceService = null;
113 }
114
115 private FlowRule flowRule(int tsval, int trval) {
116 TestSelector ts = new TestSelector(tsval);
117 TestTreatment tr = new TestTreatment(trval);
alshabiba0e04982014-10-03 13:03:19 -0700118 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700119 }
120
alshabibbb8b1282014-09-22 17:00:18 -0700121
122 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700123 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700124 service.applyFlowRules(rule);
125
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700126 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700127 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700128 }
129
130 private void validateEvents(FlowRuleEvent.Type ... events) {
131 if (events == null) {
132 assertTrue("events generated", listener.events.isEmpty());
133 }
134
135 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700136 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700137 for (FlowRuleEvent e : listener.events) {
138 assertTrue("unexpected event", e.type().equals(events[i]));
139 i++;
140 }
141
142 assertEquals("mispredicted number of events",
143 events.length, listener.events.size());
144
145 listener.events.clear();
146 }
147
148 private int flowCount() {
149 return Sets.newHashSet(service.getFlowEntries(DID)).size();
150 }
151 @Test
152 public void getFlowEntries() {
153 assertTrue("store should be empty",
154 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700155 FlowRule f1 = addFlowRule(1);
156 FlowRule f2 = addFlowRule(2);
157
alshabib1c319ff2014-10-04 20:29:09 -0700158 FlowEntry fe1 = new DefaultFlowEntry(f1);
159 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700160 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700161
alshabib1c319ff2014-10-04 20:29:09 -0700162 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700163 validateEvents(RULE_ADDED, RULE_ADDED);
164
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(
200 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));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700216 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
217
alshabib1c319ff2014-10-04 20:29:09 -0700218 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700219 //removing from north, so no events generated
220 validateEvents();
alshabib219ebaa2014-09-22 15:41:24 -0700221 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700222 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700223 validateState(ImmutableMap.of(
224 f1, FlowEntryState.PENDING_REMOVE,
225 f2, FlowEntryState.PENDING_REMOVE,
226 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700227
alshabib1c319ff2014-10-04 20:29:09 -0700228 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700229 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700230 }
231
232 @Test
233 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700234 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700235 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700236 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700237 FlowEntry fe2 = new DefaultFlowEntry(f2);
238 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700239 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700240 fe1.setState(FlowEntryState.REMOVED);
241 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700242 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
243
alshabib1c319ff2014-10-04 20:29:09 -0700244 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700245 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700246
alshabibba5ac482014-10-02 17:15:20 -0700247 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700248 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700249 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700250 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700251 validateEvents(RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700252
alshabib1c319ff2014-10-04 20:29:09 -0700253 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700254 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700255 }
256
alshabibbb8b1282014-09-22 17:00:18 -0700257 @Test
258 public void flowMetrics() {
259 FlowRule f1 = flowRule(1, 1);
260 FlowRule f2 = flowRule(2, 2);
261 FlowRule f3 = flowRule(3, 3);
262
alshabibba5ac482014-10-02 17:15:20 -0700263 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700264
alshabib1c319ff2014-10-04 20:29:09 -0700265 FlowEntry fe1 = new DefaultFlowEntry(f1);
266 FlowEntry fe2 = new DefaultFlowEntry(f2);
267
268
269 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
270 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
271
272 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700273
274 assertTrue("Entries should be added.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700275 validateState(ImmutableMap.of(
276 f1, FlowEntryState.ADDED,
277 f2, FlowEntryState.ADDED,
278 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700279
alshabibba5ac482014-10-02 17:15:20 -0700280 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700281 }
282
283 @Test
284 public void extraneousFlow() {
285 FlowRule f1 = flowRule(1, 1);
286 FlowRule f2 = flowRule(2, 2);
287 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700288 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700289
alshabib1c319ff2014-10-04 20:29:09 -0700290// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
291// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
292// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
293 FlowEntry fe1 = new DefaultFlowEntry(f1);
294 FlowEntry fe2 = new DefaultFlowEntry(f2);
295 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700296
alshabib1c319ff2014-10-04 20:29:09 -0700297
298 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700299
alshabibba5ac482014-10-02 17:15:20 -0700300 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700301
302 }
303
304 /*
305 * Tests whether a rule that was marked for removal but no flowRemoved was received
306 * is indeed removed at the next stats update.
307 */
308 @Test
309 public void flowMissingRemove() {
310 FlowRule f1 = flowRule(1, 1);
311 FlowRule f2 = flowRule(2, 2);
312 FlowRule f3 = flowRule(3, 3);
313
alshabib1c319ff2014-10-04 20:29:09 -0700314// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
315// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
316
317 FlowEntry fe1 = new DefaultFlowEntry(f1);
318 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700319 mgr.applyFlowRules(f1, f2, f3);
320
321 mgr.removeFlowRules(f3);
322
alshabib1c319ff2014-10-04 20:29:09 -0700323 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700324
alshabibba5ac482014-10-02 17:15:20 -0700325 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700326
327 }
328
329 @Test
330 public void getByAppId() {
331 FlowRule f1 = flowRule(1, 1);
332 FlowRule f2 = flowRule(2, 2);
333 mgr.applyFlowRules(f1, f2);
334
335 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700336 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700337 }
338
339 @Test
340 public void removeByAppId() {
341 FlowRule f1 = flowRule(1, 1);
342 FlowRule f2 = flowRule(2, 2);
343 mgr.applyFlowRules(f1, f2);
344
345
346 mgr.removeFlowRulesById(appId);
347
348 //only check that we are in pending remove. Events and actual remove state will
349 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700350 validateState(ImmutableMap.of(
351 f1, FlowEntryState.PENDING_REMOVE,
352 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700353 }
354
alshabibcf369912014-10-13 14:16:42 -0700355 @Test
356 public void applyBatch() {
357 FlowRule f1 = flowRule(1, 1);
358 FlowRule f2 = flowRule(2, 2);
359
360
361 mgr.applyFlowRules(f1);
362
363 FlowEntry fe1 = new DefaultFlowEntry(f1);
364 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
365
366 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
367 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
368
369 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
370 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
371
372 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
373 Lists.newArrayList(fbe1, fbe2));
374 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
375 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700376 validateState(ImmutableMap.of(
377 f1, FlowEntryState.PENDING_REMOVE,
378 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700379 CompletedBatchOperation completed = null;
380 try {
381 completed = future.get();
382 } catch (InterruptedException | ExecutionException e) {
383 fail("Unexpected exception: " + e);
384 }
385 if (!completed.isSuccess()) {
386 fail("Installation should be a success");
387 }
388
389 }
390
391 @Test
392 public void cancelBatch() {
393 FlowRule f1 = flowRule(1, 1);
394 FlowRule f2 = flowRule(2, 2);
395
396
397 mgr.applyFlowRules(f1);
398
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700399 assertTrue("Entries in wrong state",
400 validateState(ImmutableMap.of(
401 f1, FlowEntryState.PENDING_ADD)));
402
alshabibcf369912014-10-13 14:16:42 -0700403 FlowEntry fe1 = new DefaultFlowEntry(f1);
404 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
405
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700406 assertTrue("Entries in wrong state",
407 validateState(ImmutableMap.of(
408 f1, FlowEntryState.ADDED)));
409
410
alshabibcf369912014-10-13 14:16:42 -0700411 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
412 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
413
414 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
415 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
416
417 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
418 Lists.newArrayList(fbe1, fbe2));
419 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
420
421 future.cancel(true);
422
423 assertTrue(flowCount() == 2);
424
425 /*
426 * Rule f1 should be re-added to the list and therefore be in a pending add
427 * state.
428 */
429 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700430 validateState(ImmutableMap.of(
431 f2, FlowEntryState.PENDING_REMOVE,
432 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700433
434
alshabibcf369912014-10-13 14:16:42 -0700435 }
436
437
438
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700439 private static class TestListener implements FlowRuleListener {
440 final List<FlowRuleEvent> events = new ArrayList<>();
441
442 @Override
443 public void event(FlowRuleEvent event) {
444 events.add(event);
445 }
446 }
447
448 private static class TestDeviceService implements DeviceService {
449
450 @Override
451 public int getDeviceCount() {
452 return 0;
453 }
454
455 @Override
456 public Iterable<Device> getDevices() {
457 return null;
458 }
459
460 @Override
461 public Device getDevice(DeviceId deviceId) {
462 return DEV;
463 }
464
465 @Override
466 public MastershipRole getRole(DeviceId deviceId) {
467 return null;
468 }
469
470 @Override
471 public List<Port> getPorts(DeviceId deviceId) {
472 return null;
473 }
474
475 @Override
476 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
477 return null;
478 }
479
480 @Override
481 public boolean isAvailable(DeviceId deviceId) {
482 return false;
483 }
484
485 @Override
486 public void addListener(DeviceListener listener) {
487 }
488
489 @Override
490 public void removeListener(DeviceListener listener) {
491 }
492
493 }
494
495 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
496
497 protected TestProvider(ProviderId id) {
498 super(PID);
499 }
500
501 @Override
502 public void applyFlowRule(FlowRule... flowRules) {
503 }
504
505 @Override
506 public void removeFlowRule(FlowRule... flowRules) {
507 }
508
alshabiba68eb962014-09-24 20:34:13 -0700509 @Override
510 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
511 }
512
alshabib902d41b2014-10-07 16:52:05 -0700513 @Override
alshabib193525b2014-10-08 18:58:03 -0700514 public Future<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700515 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700516 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700517 }
518
alshabibcf369912014-10-13 14:16:42 -0700519 private class TestInstallationFuture
520 implements Future<CompletedBatchOperation> {
521
522 @Override
523 public boolean cancel(boolean mayInterruptIfRunning) {
524 return true;
525 }
526
527 @Override
528 public boolean isCancelled() {
529 return true;
530 }
531
532 @Override
533 public boolean isDone() {
534 return false;
535 }
536
537 @Override
538 public CompletedBatchOperation get()
539 throws InterruptedException, ExecutionException {
540 return new CompletedBatchOperation(true, EMPTY_LIST);
541 }
542
543 @Override
544 public CompletedBatchOperation get(long timeout, TimeUnit unit)
545 throws InterruptedException,
546 ExecutionException, TimeoutException {
547 return null;
548 }
549 }
alshabiba68eb962014-09-24 20:34:13 -0700550
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700551 }
552
553 private class TestSelector implements TrafficSelector {
554
555 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700556 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700557
558 public TestSelector(int val) {
559 testval = val;
560 }
561
562 @Override
alshabibba5ac482014-10-02 17:15:20 -0700563 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700564 return null;
565 }
566
567 @Override
568 public int hashCode() {
569 return testval;
570 }
571
572 @Override
573 public boolean equals(Object o) {
574 if (o instanceof TestSelector) {
575 return this.testval == ((TestSelector) o).testval;
576 }
577 return false;
578 }
579 }
580
581 private class TestTreatment implements TrafficTreatment {
582
583 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700584 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700585
586 public TestTreatment(int val) {
587 testval = val;
588 }
589
590 @Override
591 public List<Instruction> instructions() {
592 return null;
593 }
594
595 @Override
596 public int hashCode() {
597 return testval;
598 }
599
600 @Override
601 public boolean equals(Object o) {
602 if (o instanceof TestTreatment) {
603 return this.testval == ((TestTreatment) o).testval;
604 }
605 return false;
606 }
607
608 }
609
alshabib92c65ad2014-10-08 21:56:05 -0700610 public class TestApplicationId extends DefaultApplicationId {
611
612 public TestApplicationId(short id, String name) {
613 super(id, name);
614 }
615 }
616
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700617}