blob: 85ceb3f609e47e7bd7f25005e22d5cef894c7d21 [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;
Jonathan Hart936c49d2014-10-23 16:38:59 -07009import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADD_REQUESTED;
alshabib97044902014-09-18 14:52:16 -070010import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
Jonathan Hart936c49d2014-10-23 16:38:59 -070011import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVE_REQUESTED;
alshabib219ebaa2014-09-22 15:41:24 -070012import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070013
14import java.util.ArrayList;
Madan Jampani6a456162014-10-24 11:36:17 -070015import java.util.Arrays;
alshabibba5ac482014-10-02 17:15:20 -070016import java.util.Collections;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070017import java.util.HashMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070018import java.util.List;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070019import java.util.Map;
alshabibba5ac482014-10-02 17:15:20 -070020import java.util.Set;
alshabibcf369912014-10-13 14:16:42 -070021import java.util.concurrent.ExecutionException;
Madan Jampani117aaae2014-10-23 10:04:05 -070022import java.util.concurrent.Executor;
alshabib902d41b2014-10-07 16:52:05 -070023import java.util.concurrent.Future;
alshabibcf369912014-10-13 14:16:42 -070024import java.util.concurrent.TimeUnit;
25import java.util.concurrent.TimeoutException;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070026
27import org.junit.After;
28import org.junit.Before;
29import org.junit.Test;
alshabiba68eb962014-09-24 20:34:13 -070030import org.onlab.onos.ApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070031import org.onlab.onos.event.impl.TestEventDispatcher;
alshabib92c65ad2014-10-08 21:56:05 -070032import org.onlab.onos.impl.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070033import org.onlab.onos.net.DefaultDevice;
34import org.onlab.onos.net.Device;
35import org.onlab.onos.net.Device.Type;
36import org.onlab.onos.net.DeviceId;
37import org.onlab.onos.net.MastershipRole;
38import org.onlab.onos.net.Port;
39import org.onlab.onos.net.PortNumber;
40import org.onlab.onos.net.device.DeviceListener;
41import org.onlab.onos.net.device.DeviceService;
Jonathan Hart936c49d2014-10-23 16:38:59 -070042import org.onlab.onos.net.flow.BatchOperation;
alshabib193525b2014-10-08 18:58:03 -070043import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070044import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070045import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070046import org.onlab.onos.net.flow.FlowEntry;
47import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070048import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070049import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070050import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070051import org.onlab.onos.net.flow.FlowRuleEvent;
52import org.onlab.onos.net.flow.FlowRuleListener;
53import org.onlab.onos.net.flow.FlowRuleProvider;
54import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
55import org.onlab.onos.net.flow.FlowRuleProviderService;
56import org.onlab.onos.net.flow.FlowRuleService;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070057import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070058import org.onlab.onos.net.flow.TrafficSelector;
59import org.onlab.onos.net.flow.TrafficTreatment;
60import org.onlab.onos.net.flow.criteria.Criterion;
61import org.onlab.onos.net.flow.instructions.Instruction;
62import org.onlab.onos.net.provider.AbstractProvider;
63import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070064import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070065
alshabibba5ac482014-10-02 17:15:20 -070066import com.google.common.collect.ImmutableList;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070067import com.google.common.collect.ImmutableMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070068import com.google.common.collect.Lists;
69import com.google.common.collect.Sets;
Madan Jampani117aaae2014-10-23 10:04:05 -070070import com.google.common.util.concurrent.ListenableFuture;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070071
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070072/**
73 * Test codifying the flow rule service & flow rule provider service contracts.
74 */
tom202175a2014-09-19 19:00:11 -070075public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070076
alshabib92c65ad2014-10-08 21:56:05 -070077
78
tomf6ab2152014-09-18 12:08:29 -070079 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070080 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070081 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070082 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070083 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070084
tom202175a2014-09-19 19:00:11 -070085 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070086
87 protected FlowRuleService service;
88 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070089 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070090 protected TestProvider provider;
91 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070092 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070093
94 @Before
95 public void setUp() {
tom202175a2014-09-19 19:00:11 -070096 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070097 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070098 mgr.eventDispatcher = new TestEventDispatcher();
99 mgr.deviceService = new TestDeviceService();
100 service = mgr;
101 registry = mgr;
102
103 mgr.activate();
104 mgr.addListener(listener);
105 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700106 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -0700107 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700108 assertTrue("provider should be registered",
109 registry.getProviders().contains(provider.id()));
110 }
111
112 @After
113 public void tearDown() {
114 registry.unregister(provider);
115 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700116 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700117 service.removeListener(listener);
118 mgr.deactivate();
119 mgr.eventDispatcher = null;
120 mgr.deviceService = null;
121 }
122
123 private FlowRule flowRule(int tsval, int trval) {
124 TestSelector ts = new TestSelector(tsval);
125 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700126 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700127 }
128
alshabibbb8b1282014-09-22 17:00:18 -0700129
130 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700131 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700132 service.applyFlowRules(rule);
133
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700134 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700135 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700136 }
137
138 private void validateEvents(FlowRuleEvent.Type ... events) {
139 if (events == null) {
140 assertTrue("events generated", listener.events.isEmpty());
141 }
142
143 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700144 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700145 for (FlowRuleEvent e : listener.events) {
146 assertTrue("unexpected event", e.type().equals(events[i]));
147 i++;
148 }
149
150 assertEquals("mispredicted number of events",
151 events.length, listener.events.size());
152
153 listener.events.clear();
154 }
155
156 private int flowCount() {
157 return Sets.newHashSet(service.getFlowEntries(DID)).size();
158 }
159 @Test
160 public void getFlowEntries() {
161 assertTrue("store should be empty",
162 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700163 FlowRule f1 = addFlowRule(1);
164 FlowRule f2 = addFlowRule(2);
165
alshabib1c319ff2014-10-04 20:29:09 -0700166 FlowEntry fe1 = new DefaultFlowEntry(f1);
167 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700168 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700169
alshabib1c319ff2014-10-04 20:29:09 -0700170 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700171 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
172 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700173
174 addFlowRule(1);
175 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700176
alshabib1c319ff2014-10-04 20:29:09 -0700177 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700178 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700179 }
180
alshabibbb8b1282014-09-22 17:00:18 -0700181
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700182 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700183 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700184 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
185 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700186 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700187 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700188 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
189 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
190 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700191 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700192 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700193 return true;
194 }
195
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700196 @Test
197 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700198
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700199 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700200 FlowRule r2 = flowRule(2, 2);
201 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700202
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700203 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700204 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700205 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700206 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700207 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700208 validateState(ImmutableMap.of(
209 r1, FlowEntryState.PENDING_ADD,
210 r2, FlowEntryState.PENDING_ADD,
211 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700212 }
213
214 @Test
215 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700216 FlowRule f1 = addFlowRule(1);
217 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700218 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700219 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700220
alshabib1c319ff2014-10-04 20:29:09 -0700221 FlowEntry fe1 = new DefaultFlowEntry(f1);
222 FlowEntry fe2 = new DefaultFlowEntry(f2);
223 FlowEntry fe3 = new DefaultFlowEntry(f3);
224 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700225 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
226 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700227
alshabib1c319ff2014-10-04 20:29:09 -0700228 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700229 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700230 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700231 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700232 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700233 validateState(ImmutableMap.of(
234 f1, FlowEntryState.PENDING_REMOVE,
235 f2, FlowEntryState.PENDING_REMOVE,
236 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700237
alshabib1c319ff2014-10-04 20:29:09 -0700238 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700239 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700240 }
241
242 @Test
243 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700244 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700245 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700246 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700247 FlowEntry fe2 = new DefaultFlowEntry(f2);
248 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700249 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700250 fe1.setState(FlowEntryState.REMOVED);
251 providerService.flowRemoved(fe1);
alshabib3d643ec2014-10-22 18:33:00 -0700252 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
253 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700254
alshabib1c319ff2014-10-04 20:29:09 -0700255 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700256 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700257
alshabibba5ac482014-10-02 17:15:20 -0700258 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700259 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700260 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700261 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700262 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700263
alshabib1c319ff2014-10-04 20:29:09 -0700264 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700265 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700266 }
267
alshabibbb8b1282014-09-22 17:00:18 -0700268 @Test
269 public void flowMetrics() {
270 FlowRule f1 = flowRule(1, 1);
271 FlowRule f2 = flowRule(2, 2);
272 FlowRule f3 = flowRule(3, 3);
273
alshabibba5ac482014-10-02 17:15:20 -0700274 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700275
alshabib1c319ff2014-10-04 20:29:09 -0700276 FlowEntry fe1 = new DefaultFlowEntry(f1);
277 FlowEntry fe2 = new DefaultFlowEntry(f2);
278
279
280 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
281 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
282
283 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700284
285 assertTrue("Entries should be added.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700286 validateState(ImmutableMap.of(
287 f1, FlowEntryState.ADDED,
288 f2, FlowEntryState.ADDED,
289 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700290
alshabib3d643ec2014-10-22 18:33:00 -0700291 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
292 RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700293 }
294
295 @Test
296 public void extraneousFlow() {
297 FlowRule f1 = flowRule(1, 1);
298 FlowRule f2 = flowRule(2, 2);
299 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700300 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700301
alshabib1c319ff2014-10-04 20:29:09 -0700302// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
303// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
304// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
305 FlowEntry fe1 = new DefaultFlowEntry(f1);
306 FlowEntry fe2 = new DefaultFlowEntry(f2);
307 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700308
alshabib1c319ff2014-10-04 20:29:09 -0700309
310 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700311
alshabib3d643ec2014-10-22 18:33:00 -0700312 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700313
314 }
315
316 /*
317 * Tests whether a rule that was marked for removal but no flowRemoved was received
318 * is indeed removed at the next stats update.
319 */
320 @Test
321 public void flowMissingRemove() {
322 FlowRule f1 = flowRule(1, 1);
323 FlowRule f2 = flowRule(2, 2);
324 FlowRule f3 = flowRule(3, 3);
325
alshabib1c319ff2014-10-04 20:29:09 -0700326// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
327// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
328
329 FlowEntry fe1 = new DefaultFlowEntry(f1);
330 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700331 mgr.applyFlowRules(f1, f2, f3);
332
333 mgr.removeFlowRules(f3);
334
alshabib1c319ff2014-10-04 20:29:09 -0700335 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700336
alshabib3d643ec2014-10-22 18:33:00 -0700337 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
338 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700339
340 }
341
342 @Test
343 public void getByAppId() {
344 FlowRule f1 = flowRule(1, 1);
345 FlowRule f2 = flowRule(2, 2);
346 mgr.applyFlowRules(f1, f2);
347
348 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700349 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700350 }
351
352 @Test
353 public void removeByAppId() {
354 FlowRule f1 = flowRule(1, 1);
355 FlowRule f2 = flowRule(2, 2);
356 mgr.applyFlowRules(f1, f2);
357
358
359 mgr.removeFlowRulesById(appId);
360
361 //only check that we are in pending remove. Events and actual remove state will
362 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700363 validateState(ImmutableMap.of(
364 f1, FlowEntryState.PENDING_REMOVE,
365 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700366 }
367
alshabibcf369912014-10-13 14:16:42 -0700368 @Test
369 public void applyBatch() {
370 FlowRule f1 = flowRule(1, 1);
371 FlowRule f2 = flowRule(2, 2);
372
373
374 mgr.applyFlowRules(f1);
375
376 FlowEntry fe1 = new DefaultFlowEntry(f1);
377 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
378
379 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
380 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
381
382 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
383 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
384
385 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
386 Lists.newArrayList(fbe1, fbe2));
387 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
388 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700389 validateState(ImmutableMap.of(
390 f1, FlowEntryState.PENDING_REMOVE,
391 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700392 CompletedBatchOperation completed = null;
393 try {
394 completed = future.get();
395 } catch (InterruptedException | ExecutionException e) {
396 fail("Unexpected exception: " + e);
397 }
398 if (!completed.isSuccess()) {
399 fail("Installation should be a success");
400 }
401
402 }
403
404 @Test
405 public void cancelBatch() {
406 FlowRule f1 = flowRule(1, 1);
407 FlowRule f2 = flowRule(2, 2);
408
409
410 mgr.applyFlowRules(f1);
411
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700412 assertTrue("Entries in wrong state",
413 validateState(ImmutableMap.of(
414 f1, FlowEntryState.PENDING_ADD)));
415
alshabibcf369912014-10-13 14:16:42 -0700416 FlowEntry fe1 = new DefaultFlowEntry(f1);
417 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
418
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700419 assertTrue("Entries in wrong state",
420 validateState(ImmutableMap.of(
421 f1, FlowEntryState.ADDED)));
422
423
alshabibcf369912014-10-13 14:16:42 -0700424 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
425 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
426
427 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
428 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
429
430 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
431 Lists.newArrayList(fbe1, fbe2));
432 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
433
434 future.cancel(true);
435
436 assertTrue(flowCount() == 2);
437
438 /*
439 * Rule f1 should be re-added to the list and therefore be in a pending add
440 * state.
441 */
442 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700443 validateState(ImmutableMap.of(
444 f2, FlowEntryState.PENDING_REMOVE,
445 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700446
447
alshabibcf369912014-10-13 14:16:42 -0700448 }
449
450
451
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700452 private static class TestListener implements FlowRuleListener {
453 final List<FlowRuleEvent> events = new ArrayList<>();
454
455 @Override
456 public void event(FlowRuleEvent event) {
457 events.add(event);
458 }
459 }
460
461 private static class TestDeviceService implements DeviceService {
462
463 @Override
464 public int getDeviceCount() {
Madan Jampani6a456162014-10-24 11:36:17 -0700465 return 1;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700466 }
467
468 @Override
469 public Iterable<Device> getDevices() {
Madan Jampani6a456162014-10-24 11:36:17 -0700470 return Arrays.asList(DEV);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700471 }
472
473 @Override
474 public Device getDevice(DeviceId deviceId) {
475 return DEV;
476 }
477
478 @Override
479 public MastershipRole getRole(DeviceId deviceId) {
480 return null;
481 }
482
483 @Override
484 public List<Port> getPorts(DeviceId deviceId) {
485 return null;
486 }
487
488 @Override
489 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
490 return null;
491 }
492
493 @Override
494 public boolean isAvailable(DeviceId deviceId) {
495 return false;
496 }
497
498 @Override
499 public void addListener(DeviceListener listener) {
500 }
501
502 @Override
503 public void removeListener(DeviceListener listener) {
504 }
505
506 }
507
508 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
509
510 protected TestProvider(ProviderId id) {
511 super(PID);
512 }
513
514 @Override
515 public void applyFlowRule(FlowRule... flowRules) {
516 }
517
518 @Override
519 public void removeFlowRule(FlowRule... flowRules) {
520 }
521
alshabiba68eb962014-09-24 20:34:13 -0700522 @Override
523 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
524 }
525
alshabib902d41b2014-10-07 16:52:05 -0700526 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700527 public ListenableFuture<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700528 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700529 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700530 }
531
alshabibcf369912014-10-13 14:16:42 -0700532 private class TestInstallationFuture
Madan Jampani117aaae2014-10-23 10:04:05 -0700533 implements ListenableFuture<CompletedBatchOperation> {
alshabibcf369912014-10-13 14:16:42 -0700534
535 @Override
536 public boolean cancel(boolean mayInterruptIfRunning) {
537 return true;
538 }
539
540 @Override
541 public boolean isCancelled() {
542 return true;
543 }
544
545 @Override
546 public boolean isDone() {
547 return false;
548 }
549
550 @Override
551 public CompletedBatchOperation get()
552 throws InterruptedException, ExecutionException {
Madan Jampani117aaae2014-10-23 10:04:05 -0700553 return new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet());
alshabibcf369912014-10-13 14:16:42 -0700554 }
555
556 @Override
557 public CompletedBatchOperation get(long timeout, TimeUnit unit)
558 throws InterruptedException,
559 ExecutionException, TimeoutException {
560 return null;
561 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700562
563 @Override
564 public void addListener(Runnable task, Executor executor) {
565 // TODO: add stuff.
566 }
alshabibcf369912014-10-13 14:16:42 -0700567 }
alshabiba68eb962014-09-24 20:34:13 -0700568
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700569 }
570
571 private class TestSelector implements TrafficSelector {
572
573 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700574 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700575
576 public TestSelector(int val) {
577 testval = val;
578 }
579
580 @Override
alshabibba5ac482014-10-02 17:15:20 -0700581 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700582 return null;
583 }
584
585 @Override
Jonathan Hart936c49d2014-10-23 16:38:59 -0700586 public Criterion getCriterion(
587 org.onlab.onos.net.flow.criteria.Criterion.Type type) {
588 return null;
589 }
590
591 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700592 public int hashCode() {
593 return testval;
594 }
595
596 @Override
597 public boolean equals(Object o) {
598 if (o instanceof TestSelector) {
599 return this.testval == ((TestSelector) o).testval;
600 }
601 return false;
602 }
Jonathan Hart936c49d2014-10-23 16:38:59 -0700603
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700604 }
605
606 private class TestTreatment implements TrafficTreatment {
607
608 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700609 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700610
611 public TestTreatment(int val) {
612 testval = val;
613 }
614
615 @Override
616 public List<Instruction> instructions() {
617 return null;
618 }
619
620 @Override
621 public int hashCode() {
622 return testval;
623 }
624
625 @Override
626 public boolean equals(Object o) {
627 if (o instanceof TestTreatment) {
628 return this.testval == ((TestTreatment) o).testval;
629 }
630 return false;
631 }
632
633 }
634
alshabib92c65ad2014-10-08 21:56:05 -0700635 public class TestApplicationId extends DefaultApplicationId {
636
637 public TestApplicationId(short id, String name) {
638 super(id, name);
639 }
640 }
641
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700642}