blob: cb966dcef839e84307ec551616794a24d7049800 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07002
alshabibcf369912014-10-13 14:16:42 -07003import static java.util.Collections.EMPTY_LIST;
Jonathan Hartbc4a7932014-10-21 11:46:00 -07004import static org.junit.Assert.assertEquals;
5import static org.junit.Assert.assertFalse;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertTrue;
8import static org.junit.Assert.fail;
alshabib3d643ec2014-10-22 18:33:00 -07009import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070010
11import java.util.ArrayList;
alshabibba5ac482014-10-02 17:15:20 -070012import java.util.Collections;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070013import java.util.HashMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070014import java.util.List;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070015import java.util.Map;
alshabibba5ac482014-10-02 17:15:20 -070016import java.util.Set;
alshabibcf369912014-10-13 14:16:42 -070017import java.util.concurrent.ExecutionException;
alshabib902d41b2014-10-07 16:52:05 -070018import java.util.concurrent.Future;
alshabibcf369912014-10-13 14:16:42 -070019import java.util.concurrent.TimeUnit;
20import java.util.concurrent.TimeoutException;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070021
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
alshabiba68eb962014-09-24 20:34:13 -070025import org.onlab.onos.ApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070026import org.onlab.onos.event.impl.TestEventDispatcher;
alshabib92c65ad2014-10-08 21:56:05 -070027import org.onlab.onos.impl.DefaultApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070028import org.onlab.onos.net.DefaultDevice;
29import org.onlab.onos.net.Device;
30import org.onlab.onos.net.Device.Type;
31import org.onlab.onos.net.DeviceId;
32import org.onlab.onos.net.MastershipRole;
33import org.onlab.onos.net.Port;
34import org.onlab.onos.net.PortNumber;
35import org.onlab.onos.net.device.DeviceListener;
36import org.onlab.onos.net.device.DeviceService;
alshabib193525b2014-10-08 18:58:03 -070037import org.onlab.onos.net.flow.CompletedBatchOperation;
alshabib1c319ff2014-10-04 20:29:09 -070038import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070039import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070040import org.onlab.onos.net.flow.FlowEntry;
41import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070042import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070043import org.onlab.onos.net.flow.FlowRuleBatchEntry;
alshabibcf369912014-10-13 14:16:42 -070044import org.onlab.onos.net.flow.FlowRuleBatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070045import org.onlab.onos.net.flow.FlowRuleEvent;
46import org.onlab.onos.net.flow.FlowRuleListener;
47import org.onlab.onos.net.flow.FlowRuleProvider;
48import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
49import org.onlab.onos.net.flow.FlowRuleProviderService;
50import org.onlab.onos.net.flow.FlowRuleService;
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -070051import org.onlab.onos.net.flow.StoredFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070052import org.onlab.onos.net.flow.TrafficSelector;
53import org.onlab.onos.net.flow.TrafficTreatment;
54import org.onlab.onos.net.flow.criteria.Criterion;
55import org.onlab.onos.net.flow.instructions.Instruction;
alshabib902d41b2014-10-07 16:52:05 -070056import org.onlab.onos.net.intent.BatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070057import org.onlab.onos.net.provider.AbstractProvider;
58import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070059import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070060
alshabibba5ac482014-10-02 17:15:20 -070061import com.google.common.collect.ImmutableList;
Yuta HIGUCHI605347c2014-10-17 21:05:23 -070062import com.google.common.collect.ImmutableMap;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070063import com.google.common.collect.Lists;
64import com.google.common.collect.Sets;
65
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070066/**
67 * Test codifying the flow rule service & flow rule provider service contracts.
68 */
tom202175a2014-09-19 19:00:11 -070069public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070070
alshabib92c65ad2014-10-08 21:56:05 -070071
72
tomf6ab2152014-09-18 12:08:29 -070073 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070074 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070075 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070076 private static final Device DEV = new DefaultDevice(
alshabib7911a052014-10-16 17:49:37 -070077 PID, DID, Type.SWITCH, "", "", "", "", null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070078
tom202175a2014-09-19 19:00:11 -070079 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070080
81 protected FlowRuleService service;
82 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070083 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070084 protected TestProvider provider;
85 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070086 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070087
88 @Before
89 public void setUp() {
tom202175a2014-09-19 19:00:11 -070090 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070091 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070092 mgr.eventDispatcher = new TestEventDispatcher();
93 mgr.deviceService = new TestDeviceService();
94 service = mgr;
95 registry = mgr;
96
97 mgr.activate();
98 mgr.addListener(listener);
99 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -0700100 providerService = registry.register(provider);
alshabib92c65ad2014-10-08 21:56:05 -0700101 appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700102 assertTrue("provider should be registered",
103 registry.getProviders().contains(provider.id()));
104 }
105
106 @After
107 public void tearDown() {
108 registry.unregister(provider);
109 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -0700110 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700111 service.removeListener(listener);
112 mgr.deactivate();
113 mgr.eventDispatcher = null;
114 mgr.deviceService = null;
115 }
116
117 private FlowRule flowRule(int tsval, int trval) {
118 TestSelector ts = new TestSelector(tsval);
119 TestTreatment tr = new TestTreatment(trval);
Jonathan Hartbc4a7932014-10-21 11:46:00 -0700120 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT, false);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700121 }
122
alshabibbb8b1282014-09-22 17:00:18 -0700123
124 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700125 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700126 service.applyFlowRules(rule);
127
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700128 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700129 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700130 }
131
132 private void validateEvents(FlowRuleEvent.Type ... events) {
133 if (events == null) {
134 assertTrue("events generated", listener.events.isEmpty());
135 }
136
137 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700138 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700139 for (FlowRuleEvent e : listener.events) {
140 assertTrue("unexpected event", e.type().equals(events[i]));
141 i++;
142 }
143
144 assertEquals("mispredicted number of events",
145 events.length, listener.events.size());
146
147 listener.events.clear();
148 }
149
150 private int flowCount() {
151 return Sets.newHashSet(service.getFlowEntries(DID)).size();
152 }
153 @Test
154 public void getFlowEntries() {
155 assertTrue("store should be empty",
156 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700157 FlowRule f1 = addFlowRule(1);
158 FlowRule f2 = addFlowRule(2);
159
alshabib1c319ff2014-10-04 20:29:09 -0700160 FlowEntry fe1 = new DefaultFlowEntry(f1);
161 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700162 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700163
alshabib1c319ff2014-10-04 20:29:09 -0700164 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700165 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
166 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700167
168 addFlowRule(1);
169 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700170
alshabib1c319ff2014-10-04 20:29:09 -0700171 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700172 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700173 }
174
alshabibbb8b1282014-09-22 17:00:18 -0700175
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700176 // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
alshabibbb8b1282014-09-22 17:00:18 -0700177 //backing store is sensitive to the order of additions/removals
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700178 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
179 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700180 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700181 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700182 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
183 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
184 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700185 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700186 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700187 return true;
188 }
189
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700190 @Test
191 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700192
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700193 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700194 FlowRule r2 = flowRule(2, 2);
195 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700196
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700197 assertTrue("store should be empty",
alshabibcf369912014-10-13 14:16:42 -0700198 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700199 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700200 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700201 assertTrue("Entries should be pending add.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700202 validateState(ImmutableMap.of(
203 r1, FlowEntryState.PENDING_ADD,
204 r2, FlowEntryState.PENDING_ADD,
205 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700206 }
207
208 @Test
209 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700210 FlowRule f1 = addFlowRule(1);
211 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700212 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700213 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700214
alshabib1c319ff2014-10-04 20:29:09 -0700215 FlowEntry fe1 = new DefaultFlowEntry(f1);
216 FlowEntry fe2 = new DefaultFlowEntry(f2);
217 FlowEntry fe3 = new DefaultFlowEntry(f3);
218 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700219 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
220 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700221
alshabib1c319ff2014-10-04 20:29:09 -0700222 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700223 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700224 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700225 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700226 assertTrue("Entries should be pending remove.",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700227 validateState(ImmutableMap.of(
228 f1, FlowEntryState.PENDING_REMOVE,
229 f2, FlowEntryState.PENDING_REMOVE,
230 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700231
alshabib1c319ff2014-10-04 20:29:09 -0700232 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700233 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700234 }
235
236 @Test
237 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700238 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700239 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700240 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700241 FlowEntry fe2 = new DefaultFlowEntry(f2);
242 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700243 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700244 fe1.setState(FlowEntryState.REMOVED);
245 providerService.flowRemoved(fe1);
alshabib3d643ec2014-10-22 18:33:00 -0700246 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
247 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700248
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));
alshabib3d643ec2014-10-22 18:33:00 -0700256 validateEvents(RULE_ADD_REQUESTED, 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
alshabib3d643ec2014-10-22 18:33:00 -0700285 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
286 RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700287 }
288
289 @Test
290 public void extraneousFlow() {
291 FlowRule f1 = flowRule(1, 1);
292 FlowRule f2 = flowRule(2, 2);
293 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700294 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700295
alshabib1c319ff2014-10-04 20:29:09 -0700296// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
297// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
298// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
299 FlowEntry fe1 = new DefaultFlowEntry(f1);
300 FlowEntry fe2 = new DefaultFlowEntry(f2);
301 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700302
alshabib1c319ff2014-10-04 20:29:09 -0700303
304 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700305
alshabib3d643ec2014-10-22 18:33:00 -0700306 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700307
308 }
309
310 /*
311 * Tests whether a rule that was marked for removal but no flowRemoved was received
312 * is indeed removed at the next stats update.
313 */
314 @Test
315 public void flowMissingRemove() {
316 FlowRule f1 = flowRule(1, 1);
317 FlowRule f2 = flowRule(2, 2);
318 FlowRule f3 = flowRule(3, 3);
319
alshabib1c319ff2014-10-04 20:29:09 -0700320// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
321// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
322
323 FlowEntry fe1 = new DefaultFlowEntry(f1);
324 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700325 mgr.applyFlowRules(f1, f2, f3);
326
327 mgr.removeFlowRules(f3);
328
alshabib1c319ff2014-10-04 20:29:09 -0700329 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700330
alshabib3d643ec2014-10-22 18:33:00 -0700331 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
332 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700333
334 }
335
336 @Test
337 public void getByAppId() {
338 FlowRule f1 = flowRule(1, 1);
339 FlowRule f2 = flowRule(2, 2);
340 mgr.applyFlowRules(f1, f2);
341
342 assertTrue("should have two rules",
alshabibcf369912014-10-13 14:16:42 -0700343 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700344 }
345
346 @Test
347 public void removeByAppId() {
348 FlowRule f1 = flowRule(1, 1);
349 FlowRule f2 = flowRule(2, 2);
350 mgr.applyFlowRules(f1, f2);
351
352
353 mgr.removeFlowRulesById(appId);
354
355 //only check that we are in pending remove. Events and actual remove state will
356 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700357 validateState(ImmutableMap.of(
358 f1, FlowEntryState.PENDING_REMOVE,
359 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700360 }
361
alshabibcf369912014-10-13 14:16:42 -0700362 @Test
363 public void applyBatch() {
364 FlowRule f1 = flowRule(1, 1);
365 FlowRule f2 = flowRule(2, 2);
366
367
368 mgr.applyFlowRules(f1);
369
370 FlowEntry fe1 = new DefaultFlowEntry(f1);
371 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
372
373 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
374 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
375
376 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
377 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
378
379 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
380 Lists.newArrayList(fbe1, fbe2));
381 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
382 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700383 validateState(ImmutableMap.of(
384 f1, FlowEntryState.PENDING_REMOVE,
385 f2, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700386 CompletedBatchOperation completed = null;
387 try {
388 completed = future.get();
389 } catch (InterruptedException | ExecutionException e) {
390 fail("Unexpected exception: " + e);
391 }
392 if (!completed.isSuccess()) {
393 fail("Installation should be a success");
394 }
395
396 }
397
398 @Test
399 public void cancelBatch() {
400 FlowRule f1 = flowRule(1, 1);
401 FlowRule f2 = flowRule(2, 2);
402
403
404 mgr.applyFlowRules(f1);
405
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700406 assertTrue("Entries in wrong state",
407 validateState(ImmutableMap.of(
408 f1, FlowEntryState.PENDING_ADD)));
409
alshabibcf369912014-10-13 14:16:42 -0700410 FlowEntry fe1 = new DefaultFlowEntry(f1);
411 providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
412
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700413 assertTrue("Entries in wrong state",
414 validateState(ImmutableMap.of(
415 f1, FlowEntryState.ADDED)));
416
417
alshabibcf369912014-10-13 14:16:42 -0700418 FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
419 FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
420
421 FlowRuleBatchEntry fbe2 = new FlowRuleBatchEntry(
422 FlowRuleBatchEntry.FlowRuleOperation.ADD, f2);
423
424 FlowRuleBatchOperation fbo = new FlowRuleBatchOperation(
425 Lists.newArrayList(fbe1, fbe2));
426 Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
427
428 future.cancel(true);
429
430 assertTrue(flowCount() == 2);
431
432 /*
433 * Rule f1 should be re-added to the list and therefore be in a pending add
434 * state.
435 */
436 assertTrue("Entries in wrong state",
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700437 validateState(ImmutableMap.of(
438 f2, FlowEntryState.PENDING_REMOVE,
439 f1, FlowEntryState.PENDING_ADD)));
alshabibcf369912014-10-13 14:16:42 -0700440
441
alshabibcf369912014-10-13 14:16:42 -0700442 }
443
444
445
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700446 private static class TestListener implements FlowRuleListener {
447 final List<FlowRuleEvent> events = new ArrayList<>();
448
449 @Override
450 public void event(FlowRuleEvent event) {
451 events.add(event);
452 }
453 }
454
455 private static class TestDeviceService implements DeviceService {
456
457 @Override
458 public int getDeviceCount() {
459 return 0;
460 }
461
462 @Override
463 public Iterable<Device> getDevices() {
464 return null;
465 }
466
467 @Override
468 public Device getDevice(DeviceId deviceId) {
469 return DEV;
470 }
471
472 @Override
473 public MastershipRole getRole(DeviceId deviceId) {
474 return null;
475 }
476
477 @Override
478 public List<Port> getPorts(DeviceId deviceId) {
479 return null;
480 }
481
482 @Override
483 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
484 return null;
485 }
486
487 @Override
488 public boolean isAvailable(DeviceId deviceId) {
489 return false;
490 }
491
492 @Override
493 public void addListener(DeviceListener listener) {
494 }
495
496 @Override
497 public void removeListener(DeviceListener listener) {
498 }
499
500 }
501
502 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
503
504 protected TestProvider(ProviderId id) {
505 super(PID);
506 }
507
508 @Override
509 public void applyFlowRule(FlowRule... flowRules) {
510 }
511
512 @Override
513 public void removeFlowRule(FlowRule... flowRules) {
514 }
515
alshabiba68eb962014-09-24 20:34:13 -0700516 @Override
517 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
518 }
519
alshabib902d41b2014-10-07 16:52:05 -0700520 @Override
alshabib193525b2014-10-08 18:58:03 -0700521 public Future<CompletedBatchOperation> executeBatch(
alshabib902d41b2014-10-07 16:52:05 -0700522 BatchOperation<FlowRuleBatchEntry> batch) {
alshabibcf369912014-10-13 14:16:42 -0700523 return new TestInstallationFuture();
alshabib902d41b2014-10-07 16:52:05 -0700524 }
525
alshabibcf369912014-10-13 14:16:42 -0700526 private class TestInstallationFuture
527 implements Future<CompletedBatchOperation> {
528
529 @Override
530 public boolean cancel(boolean mayInterruptIfRunning) {
531 return true;
532 }
533
534 @Override
535 public boolean isCancelled() {
536 return true;
537 }
538
539 @Override
540 public boolean isDone() {
541 return false;
542 }
543
544 @Override
545 public CompletedBatchOperation get()
546 throws InterruptedException, ExecutionException {
547 return new CompletedBatchOperation(true, EMPTY_LIST);
548 }
549
550 @Override
551 public CompletedBatchOperation get(long timeout, TimeUnit unit)
552 throws InterruptedException,
553 ExecutionException, TimeoutException {
554 return null;
555 }
556 }
alshabiba68eb962014-09-24 20:34:13 -0700557
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700558 }
559
560 private class TestSelector implements TrafficSelector {
561
562 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700563 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700564
565 public TestSelector(int val) {
566 testval = val;
567 }
568
569 @Override
alshabibba5ac482014-10-02 17:15:20 -0700570 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700571 return null;
572 }
573
574 @Override
575 public int hashCode() {
576 return testval;
577 }
578
579 @Override
580 public boolean equals(Object o) {
581 if (o instanceof TestSelector) {
582 return this.testval == ((TestSelector) o).testval;
583 }
584 return false;
585 }
586 }
587
588 private class TestTreatment implements TrafficTreatment {
589
590 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700591 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700592
593 public TestTreatment(int val) {
594 testval = val;
595 }
596
597 @Override
598 public List<Instruction> instructions() {
599 return null;
600 }
601
602 @Override
603 public int hashCode() {
604 return testval;
605 }
606
607 @Override
608 public boolean equals(Object o) {
609 if (o instanceof TestTreatment) {
610 return this.testval == ((TestTreatment) o).testval;
611 }
612 return false;
613 }
614
615 }
616
alshabib92c65ad2014-10-08 21:56:05 -0700617 public class TestApplicationId extends DefaultApplicationId {
618
619 public TestApplicationId(short id, String name) {
620 super(id, name);
621 }
622 }
623
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700624}