blob: 659a2c41ed543906be241df9bf6bc572ccc2a21d [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;
alshabibba5ac482014-10-02 17:15:20 -070015import java.util.Collections;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070016import java.util.HashMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070017import java.util.List;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070018import java.util.Map;
alshabibba5ac482014-10-02 17:15:20 -070019import java.util.Set;
alshabibcf369912014-10-13 14:16:42 -070020import java.util.concurrent.ExecutionException;
Madan Jampani117aaae2014-10-23 10:04:05 -070021import java.util.concurrent.Executor;
alshabib902d41b2014-10-07 16:52:05 -070022import java.util.concurrent.Future;
alshabibcf369912014-10-13 14:16:42 -070023import java.util.concurrent.TimeUnit;
24import java.util.concurrent.TimeoutException;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070025
26import org.junit.After;
27import org.junit.Before;
28import org.junit.Test;
alshabiba68eb962014-09-24 20:34:13 -070029import org.onlab.onos.ApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070030import org.onlab.onos.event.impl.TestEventDispatcher;
alshabib92c65ad2014-10-08 21:56:05 -070031import org.onlab.onos.impl.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070032import org.onlab.onos.net.DefaultDevice;
33import org.onlab.onos.net.Device;
34import org.onlab.onos.net.Device.Type;
35import org.onlab.onos.net.DeviceId;
36import org.onlab.onos.net.MastershipRole;
37import org.onlab.onos.net.Port;
38import org.onlab.onos.net.PortNumber;
39import org.onlab.onos.net.device.DeviceListener;
40import org.onlab.onos.net.device.DeviceService;
Jonathan Hart936c49d2014-10-23 16:38:59 -070041import org.onlab.onos.net.flow.BatchOperation;
alshabib193525b2014-10-08 18:58:03 -070042import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070043import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070044import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070045import org.onlab.onos.net.flow.FlowEntry;
46import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070047import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070048import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070049import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070050import org.onlab.onos.net.flow.FlowRuleEvent;
51import org.onlab.onos.net.flow.FlowRuleListener;
52import org.onlab.onos.net.flow.FlowRuleProvider;
53import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
54import org.onlab.onos.net.flow.FlowRuleProviderService;
55import org.onlab.onos.net.flow.FlowRuleService;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070056import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070057import org.onlab.onos.net.flow.TrafficSelector;
58import org.onlab.onos.net.flow.TrafficTreatment;
59import org.onlab.onos.net.flow.criteria.Criterion;
60import org.onlab.onos.net.flow.instructions.Instruction;
61import org.onlab.onos.net.provider.AbstractProvider;
62import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070063import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070064
alshabibba5ac482014-10-02 17:15:20 -070065import com.google.common.collect.ImmutableList;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070066import com.google.common.collect.ImmutableMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070067import com.google.common.collect.Lists;
68import com.google.common.collect.Sets;
Madan Jampani117aaae2014-10-23 10:04:05 -070069import com.google.common.util.concurrent.ListenableFuture;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070070
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070071/**
72 * Test codifying the flow rule service & flow rule provider service contracts.
73 */
tom202175a2014-09-19 19:00:11 -070074public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070075
alshabib92c65ad2014-10-08 21:56:05 -070076
77
tomf6ab2152014-09-18 12:08:29 -070078 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070079 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070080 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070081 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070082 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070083
tom202175a2014-09-19 19:00:11 -070084 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070085
86 protected FlowRuleService service;
87 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070088 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070089 protected TestProvider provider;
90 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070091 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070092
93 @Before
94 public void setUp() {
tom202175a2014-09-19 19:00:11 -070095 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070096 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070097 mgr.eventDispatcher = new TestEventDispatcher();
98 mgr.deviceService = new TestDeviceService();
99 service = mgr;
100 registry = mgr;
101
102 mgr.activate();
103 mgr.addListener(listener);
104 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700105 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -0700106 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700107 assertTrue("provider should be registered",
108 registry.getProviders().contains(provider.id()));
109 }
110
111 @After
112 public void tearDown() {
113 registry.unregister(provider);
114 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700115 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700116 service.removeListener(listener);
117 mgr.deactivate();
118 mgr.eventDispatcher = null;
119 mgr.deviceService = null;
120 }
121
122 private FlowRule flowRule(int tsval, int trval) {
123 TestSelector ts = new TestSelector(tsval);
124 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700125 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700126 }
127
alshabibbb8b1282014-09-22 17:00:18 -0700128
129 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700130 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700131 service.applyFlowRules(rule);
132
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700133 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700134 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700135 }
136
137 private void validateEvents(FlowRuleEvent.Type ... events) {
138 if (events == null) {
139 assertTrue("events generated", listener.events.isEmpty());
140 }
141
142 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700143 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700144 for (FlowRuleEvent e : listener.events) {
145 assertTrue("unexpected event", e.type().equals(events[i]));
146 i++;
147 }
148
149 assertEquals("mispredicted number of events",
150 events.length, listener.events.size());
151
152 listener.events.clear();
153 }
154
155 private int flowCount() {
156 return Sets.newHashSet(service.getFlowEntries(DID)).size();
157 }
158 @Test
159 public void getFlowEntries() {
160 assertTrue("store should be empty",
161 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700162 FlowRule f1 = addFlowRule(1);
163 FlowRule f2 = addFlowRule(2);
164
alshabib1c319ff2014-10-04 20:29:09 -0700165 FlowEntry fe1 = new DefaultFlowEntry(f1);
166 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700167 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700168
alshabib1c319ff2014-10-04 20:29:09 -0700169 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700170 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
171 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700172
173 addFlowRule(1);
174 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700175
alshabib1c319ff2014-10-04 20:29:09 -0700176 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700177 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700178 }
179
alshabibbb8b1282014-09-22 17:00:18 -0700180
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700181 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700182 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700183 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
184 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700185 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700186 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700187 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
188 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
189 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700190 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700191 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700192 return true;
193 }
194
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700195 @Test
196 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700197
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700198 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700199 FlowRule r2 = flowRule(2, 2);
200 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700201
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700202 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700203 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700204 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700205 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700206 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700207 validateState(ImmutableMap.of(
208 r1, FlowEntryState.PENDING_ADD,
209 r2, FlowEntryState.PENDING_ADD,
210 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700211 }
212
213 @Test
214 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700215 FlowRule f1 = addFlowRule(1);
216 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700217 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700218 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700219
alshabib1c319ff2014-10-04 20:29:09 -0700220 FlowEntry fe1 = new DefaultFlowEntry(f1);
221 FlowEntry fe2 = new DefaultFlowEntry(f2);
222 FlowEntry fe3 = new DefaultFlowEntry(f3);
223 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700224 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
225 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700226
alshabib1c319ff2014-10-04 20:29:09 -0700227 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700228 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700229 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700230 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700231 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700232 validateState(ImmutableMap.of(
233 f1, FlowEntryState.PENDING_REMOVE,
234 f2, FlowEntryState.PENDING_REMOVE,
235 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700236
alshabib1c319ff2014-10-04 20:29:09 -0700237 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700238 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700239 }
240
241 @Test
242 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700243 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700244 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700245 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700246 FlowEntry fe2 = new DefaultFlowEntry(f2);
247 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700248 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700249 fe1.setState(FlowEntryState.REMOVED);
250 providerService.flowRemoved(fe1);
alshabib3d643ec2014-10-22 18:33:00 -0700251 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
252 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700253
alshabib1c319ff2014-10-04 20:29:09 -0700254 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700255 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700256
alshabibba5ac482014-10-02 17:15:20 -0700257 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700258 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700259 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700260 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700261 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700262
alshabib1c319ff2014-10-04 20:29:09 -0700263 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700264 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700265 }
266
alshabibbb8b1282014-09-22 17:00:18 -0700267 @Test
268 public void flowMetrics() {
269 FlowRule f1 = flowRule(1, 1);
270 FlowRule f2 = flowRule(2, 2);
271 FlowRule f3 = flowRule(3, 3);
272
alshabibba5ac482014-10-02 17:15:20 -0700273 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700274
alshabib1c319ff2014-10-04 20:29:09 -0700275 FlowEntry fe1 = new DefaultFlowEntry(f1);
276 FlowEntry fe2 = new DefaultFlowEntry(f2);
277
278
279 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
280 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
281
282 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700283
284 assertTrue("Entries should be added.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700285 validateState(ImmutableMap.of(
286 f1, FlowEntryState.ADDED,
287 f2, FlowEntryState.ADDED,
288 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700289
alshabib3d643ec2014-10-22 18:33:00 -0700290 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
291 RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700292 }
293
294 @Test
295 public void extraneousFlow() {
296 FlowRule f1 = flowRule(1, 1);
297 FlowRule f2 = flowRule(2, 2);
298 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700299 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700300
alshabib1c319ff2014-10-04 20:29:09 -0700301// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
302// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
303// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
304 FlowEntry fe1 = new DefaultFlowEntry(f1);
305 FlowEntry fe2 = new DefaultFlowEntry(f2);
306 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700307
alshabib1c319ff2014-10-04 20:29:09 -0700308
309 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700310
alshabib3d643ec2014-10-22 18:33:00 -0700311 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700312
313 }
314
315 /*
316 * Tests whether a rule that was marked for removal but no flowRemoved was received
317 * is indeed removed at the next stats update.
318 */
319 @Test
320 public void flowMissingRemove() {
321 FlowRule f1 = flowRule(1, 1);
322 FlowRule f2 = flowRule(2, 2);
323 FlowRule f3 = flowRule(3, 3);
324
alshabib1c319ff2014-10-04 20:29:09 -0700325// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
326// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
327
328 FlowEntry fe1 = new DefaultFlowEntry(f1);
329 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700330 mgr.applyFlowRules(f1, f2, f3);
331
332 mgr.removeFlowRules(f3);
333
alshabib1c319ff2014-10-04 20:29:09 -0700334 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700335
alshabib3d643ec2014-10-22 18:33:00 -0700336 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
337 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700338
339 }
340
341 @Test
342 public void getByAppId() {
343 FlowRule f1 = flowRule(1, 1);
344 FlowRule f2 = flowRule(2, 2);
345 mgr.applyFlowRules(f1, f2);
346
347 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700348 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700349 }
350
351 @Test
352 public void removeByAppId() {
353 FlowRule f1 = flowRule(1, 1);
354 FlowRule f2 = flowRule(2, 2);
355 mgr.applyFlowRules(f1, f2);
356
357
358 mgr.removeFlowRulesById(appId);
359
360 //only check that we are in pending remove. Events and actual remove state will
361 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700362 validateState(ImmutableMap.of(
363 f1, FlowEntryState.PENDING_REMOVE,
364 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700365 }
366
alshabibcf369912014-10-13 14:16:42 -0700367 @Test
368 public void applyBatch() {
369 FlowRule f1 = flowRule(1, 1);
370 FlowRule f2 = flowRule(2, 2);
371
372
373 mgr.applyFlowRules(f1);
374
375 FlowEntry fe1 = new DefaultFlowEntry(f1);
376 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
377
378 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
379 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
380
381 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
382 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
383
384 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
385 Lists.newArrayList(fbe1, fbe2));
386 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
387 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700388 validateState(ImmutableMap.of(
389 f1, FlowEntryState.PENDING_REMOVE,
390 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700391 CompletedBatchOperation completed = null;
392 try {
393 completed = future.get();
394 } catch (InterruptedException | ExecutionException e) {
395 fail("Unexpected exception: " + e);
396 }
397 if (!completed.isSuccess()) {
398 fail("Installation should be a success");
399 }
400
401 }
402
403 @Test
404 public void cancelBatch() {
405 FlowRule f1 = flowRule(1, 1);
406 FlowRule f2 = flowRule(2, 2);
407
408
409 mgr.applyFlowRules(f1);
410
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700411 assertTrue("Entries in wrong state",
412 validateState(ImmutableMap.of(
413 f1, FlowEntryState.PENDING_ADD)));
414
alshabibcf369912014-10-13 14:16:42 -0700415 FlowEntry fe1 = new DefaultFlowEntry(f1);
416 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
417
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700418 assertTrue("Entries in wrong state",
419 validateState(ImmutableMap.of(
420 f1, FlowEntryState.ADDED)));
421
422
alshabibcf369912014-10-13 14:16:42 -0700423 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
424 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
425
426 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
427 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
428
429 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
430 Lists.newArrayList(fbe1, fbe2));
431 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
432
433 future.cancel(true);
434
435 assertTrue(flowCount() == 2);
436
437 /*
438 * Rule f1 should be re-added to the list and therefore be in a pending add
439 * state.
440 */
441 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700442 validateState(ImmutableMap.of(
443 f2, FlowEntryState.PENDING_REMOVE,
444 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700445
446
alshabibcf369912014-10-13 14:16:42 -0700447 }
448
449
450
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700451 private static class TestListener implements FlowRuleListener {
452 final List<FlowRuleEvent> events = new ArrayList<>();
453
454 @Override
455 public void event(FlowRuleEvent event) {
456 events.add(event);
457 }
458 }
459
460 private static class TestDeviceService implements DeviceService {
461
462 @Override
463 public int getDeviceCount() {
464 return 0;
465 }
466
467 @Override
468 public Iterable<Device> getDevices() {
469 return null;
470 }
471
472 @Override
473 public Device getDevice(DeviceId deviceId) {
474 return DEV;
475 }
476
477 @Override
478 public MastershipRole getRole(DeviceId deviceId) {
479 return null;
480 }
481
482 @Override
483 public List<Port> getPorts(DeviceId deviceId) {
484 return null;
485 }
486
487 @Override
488 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
489 return null;
490 }
491
492 @Override
493 public boolean isAvailable(DeviceId deviceId) {
494 return false;
495 }
496
497 @Override
498 public void addListener(DeviceListener listener) {
499 }
500
501 @Override
502 public void removeListener(DeviceListener listener) {
503 }
504
505 }
506
507 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
508
509 protected TestProvider(ProviderId id) {
510 super(PID);
511 }
512
513 @Override
514 public void applyFlowRule(FlowRule... flowRules) {
515 }
516
517 @Override
518 public void removeFlowRule(FlowRule... flowRules) {
519 }
520
alshabiba68eb962014-09-24 20:34:13 -0700521 @Override
522 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
523 }
524
alshabib902d41b2014-10-07 16:52:05 -0700525 @Override
Madan Jampani117aaae2014-10-23 10:04:05 -0700526 public ListenableFuture<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700527 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700528 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700529 }
530
alshabibcf369912014-10-13 14:16:42 -0700531 private class TestInstallationFuture
Madan Jampani117aaae2014-10-23 10:04:05 -0700532 implements ListenableFuture<CompletedBatchOperation> {
alshabibcf369912014-10-13 14:16:42 -0700533
534 @Override
535 public boolean cancel(boolean mayInterruptIfRunning) {
536 return true;
537 }
538
539 @Override
540 public boolean isCancelled() {
541 return true;
542 }
543
544 @Override
545 public boolean isDone() {
546 return false;
547 }
548
549 @Override
550 public CompletedBatchOperation get()
551 throws InterruptedException, ExecutionException {
Madan Jampani117aaae2014-10-23 10:04:05 -0700552 return new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet());
alshabibcf369912014-10-13 14:16:42 -0700553 }
554
555 @Override
556 public CompletedBatchOperation get(long timeout, TimeUnit unit)
557 throws InterruptedException,
558 ExecutionException, TimeoutException {
559 return null;
560 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700561
562 @Override
563 public void addListener(Runnable task, Executor executor) {
564 // TODO: add stuff.
565 }
alshabibcf369912014-10-13 14:16:42 -0700566 }
alshabiba68eb962014-09-24 20:34:13 -0700567
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700568 }
569
570 private class TestSelector implements TrafficSelector {
571
572 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700573 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700574
575 public TestSelector(int val) {
576 testval = val;
577 }
578
579 @Override
alshabibba5ac482014-10-02 17:15:20 -0700580 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700581 return null;
582 }
583
584 @Override
Jonathan Hart936c49d2014-10-23 16:38:59 -0700585 public Criterion getCriterion(
586 org.onlab.onos.net.flow.criteria.Criterion.Type type) {
587 return null;
588 }
589
590 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700591 public int hashCode() {
592 return testval;
593 }
594
595 @Override
596 public boolean equals(Object o) {
597 if (o instanceof TestSelector) {
598 return this.testval == ((TestSelector) o).testval;
599 }
600 return false;
601 }
Jonathan Hart936c49d2014-10-23 16:38:59 -0700602
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700603 }
604
605 private class TestTreatment implements TrafficTreatment {
606
607 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700608 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700609
610 public TestTreatment(int val) {
611 testval = val;
612 }
613
614 @Override
615 public List<Instruction> instructions() {
616 return null;
617 }
618
619 @Override
620 public int hashCode() {
621 return testval;
622 }
623
624 @Override
625 public boolean equals(Object o) {
626 if (o instanceof TestTreatment) {
627 return this.testval == ((TestTreatment) o).testval;
628 }
629 return false;
630 }
631
632 }
633
alshabib92c65ad2014-10-08 21:56:05 -0700634 public class TestApplicationId extends DefaultApplicationId {
635
636 public TestApplicationId(short id, String name) {
637 super(id, name);
638 }
639 }
640
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700641}