blob: 7622409823fbf9828e048d3a21de8ced69ea7fe5 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070017
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070018import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableMap;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Sets;
22import com.google.common.util.concurrent.ListenableFuture;
23import com.google.common.util.concurrent.MoreExecutors;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070024import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080027import org.onlab.junit.TestTools;
pier7aceddf2019-12-19 16:04:23 +010028import org.onlab.packet.Ip4Address;
Marc De Leenheerde47caa2015-04-24 11:27:44 -070029import org.onosproject.cfg.ComponentConfigAdapter;
pier7aceddf2019-12-19 16:04:23 +010030import org.onosproject.cluster.ClusterService;
31import org.onosproject.cluster.ControllerNode;
32import org.onosproject.cluster.NodeId;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080033import org.onosproject.common.event.impl.TestEventDispatcher;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.core.ApplicationId;
Ray Milkeycc53abd2015-02-19 12:31:33 -080035import org.onosproject.core.CoreServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.core.DefaultApplicationId;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080037import org.onosproject.core.IdGenerator;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080038import org.onosproject.mastership.MastershipServiceAdapter;
39import org.onosproject.net.AnnotationKeys;
40import org.onosproject.net.DefaultAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.DefaultDevice;
42import org.onosproject.net.Device;
43import org.onosproject.net.Device.Type;
44import org.onosproject.net.DeviceId;
45import org.onosproject.net.MastershipRole;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.device.DeviceServiceAdapter;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080047import org.onosproject.net.driver.AbstractHandlerBehaviour;
48import org.onosproject.net.driver.DefaultDriver;
Thomas Vachuska11b99fc2017-04-27 12:51:04 -070049import org.onosproject.net.driver.DriverRegistry;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080050import org.onosproject.net.driver.impl.DriverManager;
Thomas Vachuska11b99fc2017-04-27 12:51:04 -070051import org.onosproject.net.driver.impl.DriverRegistryManager;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.flow.CompletedBatchOperation;
53import org.onosproject.net.flow.DefaultFlowEntry;
54import org.onosproject.net.flow.DefaultFlowRule;
55import org.onosproject.net.flow.FlowEntry;
56import org.onosproject.net.flow.FlowEntry.FlowEntryState;
57import org.onosproject.net.flow.FlowRule;
Ray Milkey7bf273c2017-09-27 16:15:15 -070058import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
Brian O'Connorabafb502014-12-02 22:26:20 -080059import org.onosproject.net.flow.FlowRuleEvent;
60import org.onosproject.net.flow.FlowRuleListener;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080061import org.onosproject.net.flow.FlowRuleProgrammable;
Brian O'Connorabafb502014-12-02 22:26:20 -080062import org.onosproject.net.flow.FlowRuleProvider;
63import org.onosproject.net.flow.FlowRuleProviderRegistry;
64import org.onosproject.net.flow.FlowRuleProviderService;
65import org.onosproject.net.flow.FlowRuleService;
66import org.onosproject.net.flow.StoredFlowEntry;
67import org.onosproject.net.flow.TrafficSelector;
68import org.onosproject.net.flow.TrafficTreatment;
69import org.onosproject.net.flow.criteria.Criterion;
70import org.onosproject.net.flow.instructions.Instruction;
alshabib346b5b32015-03-06 00:42:16 -080071import org.onosproject.net.flow.instructions.Instructions;
Saurav Das86af8f12015-05-25 23:55:33 -070072import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080073import org.onosproject.net.provider.AbstractProvider;
74import org.onosproject.net.provider.ProviderId;
Thomas Vachuskac97aa612015-06-23 16:00:18 -070075import org.onosproject.store.trivial.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070076
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070077import java.util.ArrayList;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080078import java.util.Collection;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070079import java.util.Collections;
80import java.util.HashMap;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080081import java.util.HashSet;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070082import java.util.List;
83import java.util.Map;
84import java.util.Set;
85import java.util.concurrent.ExecutionException;
86import java.util.concurrent.Executor;
87import java.util.concurrent.TimeUnit;
88import java.util.concurrent.TimeoutException;
89import java.util.concurrent.atomic.AtomicLong;
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070090
pier7aceddf2019-12-19 16:04:23 +010091import static org.easymock.EasyMock.*;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080092import static org.junit.Assert.*;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070093import static org.onosproject.net.NetTestTools.injectEventDispatcher;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080094import static org.onosproject.net.flow.FlowRuleEvent.Type.*;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070095
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070096/**
97 * Test codifying the flow rule service & flow rule provider service contracts.
98 */
tom202175a2014-09-19 19:00:11 -070099public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700100
alshabib92c65ad2014-10-08 21:56:05 -0700101
tomf6ab2152014-09-18 12:08:29 -0700102 private static final ProviderId PID = new ProviderId("of", "foo");
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800103 private static final ProviderId FOO_PID = new ProviderId("foo", "foo");
104
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700105 private static final DeviceId DID = DeviceId.deviceId("of:001");
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800106 private static final DeviceId FOO_DID = DeviceId.deviceId("foo:002");
alshabibba5ac482014-10-02 17:15:20 -0700107 private static final int TIMEOUT = 10;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800108
109 private static final DefaultAnnotations ANNOTATIONS =
110 DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, "foo").build();
111
112 private static final Device DEV =
113 new DefaultDevice(PID, DID, Type.SWITCH, "", "", "", "", null);
114 private static final Device FOO_DEV =
115 new DefaultDevice(FOO_PID, FOO_DID, Type.SWITCH, "", "", "", "", null, ANNOTATIONS);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700116
tom202175a2014-09-19 19:00:11 -0700117 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700118
119 protected FlowRuleService service;
120 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -0700121 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700122 protected TestProvider provider;
123 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -0700124 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700125
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800126 private TestDriverManager driverService;
pier7aceddf2019-12-19 16:04:23 +0100127 private static final String NODE_ID = "1";
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800128
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700129 @Before
130 public void setUp() {
tom202175a2014-09-19 19:00:11 -0700131 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -0700132 mgr.store = new SimpleFlowRuleStore();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700133 injectEventDispatcher(mgr, new TestEventDispatcher());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700134 mgr.deviceService = new TestDeviceService();
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800135 mgr.mastershipService = new TestMastershipService();
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800136 mgr.coreService = new TestCoreService();
137 mgr.operationsService = MoreExecutors.newDirectExecutorService();
138 mgr.deviceInstallers = MoreExecutors.newDirectExecutorService();
Marc De Leenheerde47caa2015-04-24 11:27:44 -0700139 mgr.cfgService = new ComponentConfigAdapter();
pier7aceddf2019-12-19 16:04:23 +0100140
141 ClusterService mockClusterService = createMock(ClusterService.class);
142 NodeId nodeId = new NodeId(NODE_ID);
143 MockControllerNode mockControllerNode = new MockControllerNode(nodeId);
144 expect(mockClusterService.getLocalNode())
145 .andReturn(mockControllerNode).anyTimes();
146 replay(mockClusterService);
147 mgr.clusterService = mockClusterService;
148
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700149 service = mgr;
150 registry = mgr;
151
Thomas Vachuska11b99fc2017-04-27 12:51:04 -0700152 DriverRegistryManager driverRegistry = new DriverRegistryManager();
153 driverService = new TestDriverManager(driverRegistry);
154 driverRegistry.addDriver(new DefaultDriver("foo", ImmutableList.of(), "", "", "",
155 ImmutableMap.of(FlowRuleProgrammable.class,
156 TestFlowRuleProgrammable.class),
157 ImmutableMap.of()));
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800158
Marc De Leenheerde47caa2015-04-24 11:27:44 -0700159 mgr.activate(null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700160 mgr.addListener(listener);
161 provider = new TestProvider(PID);
Thomas Vachuska11b99fc2017-04-27 12:51:04 -0700162 providerService = this.registry.register(provider);
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800163 appId = new TestApplicationId(0, "FlowRuleManagerTest");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700164 assertTrue("provider should be registered",
Thomas Vachuska11b99fc2017-04-27 12:51:04 -0700165 this.registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700166 }
167
168 @After
169 public void tearDown() {
170 registry.unregister(provider);
171 assertFalse("provider should not be registered",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700172 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700173 service.removeListener(listener);
174 mgr.deactivate();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700175 injectEventDispatcher(mgr, null);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700176 mgr.deviceService = null;
177 }
178
179 private FlowRule flowRule(int tsval, int trval) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800180 return flowRule(DID, tsval, trval);
181 }
182
183 private FlowRule flowRule(DeviceId did, int tsval, int trval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700184 TestSelector ts = new TestSelector(tsval);
185 TestTreatment tr = new TestTreatment(trval);
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700186 return DefaultFlowRule.builder()
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800187 .forDevice(did)
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700188 .withSelector(ts)
189 .withTreatment(tr)
190 .withPriority(10)
191 .fromApp(appId)
192 .makeTemporary(TIMEOUT)
193 .build();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700194 }
195
alshabibbb8b1282014-09-22 17:00:18 -0700196 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700197 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700198 service.applyFlowRules(rule);
199
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700200 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700201 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700202 }
203
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700204 private void validateEvents(FlowRuleEvent.Type... events) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700205 if (events == null) {
206 assertTrue("events generated", listener.events.isEmpty());
207 }
208
209 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700210 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700211 for (FlowRuleEvent e : listener.events) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800212 assertEquals("unexpected event", events[i], e.type());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700213 i++;
214 }
215
216 assertEquals("mispredicted number of events",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700217 events.length, listener.events.size());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700218
219 listener.events.clear();
220 }
221
222 private int flowCount() {
223 return Sets.newHashSet(service.getFlowEntries(DID)).size();
224 }
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700225
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700226 @Test
227 public void getFlowEntries() {
228 assertTrue("store should be empty",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700229 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700230 FlowRule f1 = addFlowRule(1);
231 FlowRule f2 = addFlowRule(2);
232
alshabib1c319ff2014-10-04 20:29:09 -0700233 FlowEntry fe1 = new DefaultFlowEntry(f1);
234 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700235 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700236
alshabib1c319ff2014-10-04 20:29:09 -0700237 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabib3d643ec2014-10-22 18:33:00 -0700238 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
239 RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700240
241 addFlowRule(1);
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800242 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700243 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700244
alshabib1c319ff2014-10-04 20:29:09 -0700245 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
Charles Chan93fa7272016-01-26 22:27:02 -0800246 validateEvents(RULE_UPDATED, RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700247 }
248
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700249 private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
250 Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
alshabib1c319ff2014-10-04 20:29:09 -0700251 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabib1c319ff2014-10-04 20:29:09 -0700252 for (FlowEntry f : rules) {
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700253 assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
254 assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
255 expectedToCheck.remove(f);
alshabibbb8b1282014-09-22 17:00:18 -0700256 }
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700257 assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
alshabibbb8b1282014-09-22 17:00:18 -0700258 return true;
259 }
260
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700261 @Test
262 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700263
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700264 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700265 FlowRule r2 = flowRule(2, 2);
266 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700267
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700268 assertTrue("store should be empty",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800269 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700270 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700271 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700272 assertTrue("Entries should be pending add.",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800273 validateState(ImmutableMap.of(
274 r1, FlowEntryState.PENDING_ADD,
275 r2, FlowEntryState.PENDING_ADD,
276 r3, FlowEntryState.PENDING_ADD)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700277 }
278
279 @Test
Kavitha Alagesanc69c66a2016-06-15 14:26:04 +0530280 public void purgeFlowRules() {
281 FlowRule f1 = addFlowRule(1);
282 FlowRule f2 = addFlowRule(2);
283 FlowRule f3 = addFlowRule(3);
284 assertEquals("3 rules should exist", 3, flowCount());
285 FlowEntry fe1 = new DefaultFlowEntry(f1);
286 FlowEntry fe2 = new DefaultFlowEntry(f2);
287 FlowEntry fe3 = new DefaultFlowEntry(f3);
288 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
289 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
Thomas Vachuska11b99fc2017-04-27 12:51:04 -0700290 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Kavitha Alagesanc69c66a2016-06-15 14:26:04 +0530291 mgr.purgeFlowRules(DID);
292 assertEquals("0 rule should exist", 0, flowCount());
293 }
294
295 @Test
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700296 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700297 FlowRule f1 = addFlowRule(1);
298 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700299 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700300 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700301
alshabib1c319ff2014-10-04 20:29:09 -0700302 FlowEntry fe1 = new DefaultFlowEntry(f1);
303 FlowEntry fe2 = new DefaultFlowEntry(f2);
304 FlowEntry fe3 = new DefaultFlowEntry(f3);
305 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
alshabib3d643ec2014-10-22 18:33:00 -0700306 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
307 RULE_ADDED, RULE_ADDED, RULE_ADDED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700308
alshabib1c319ff2014-10-04 20:29:09 -0700309 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700310 //removing from north, so no events generated
alshabib3d643ec2014-10-22 18:33:00 -0700311 validateEvents(RULE_REMOVE_REQUESTED, RULE_REMOVE_REQUESTED);
alshabib219ebaa2014-09-22 15:41:24 -0700312 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700313 assertTrue("Entries should be pending remove.",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800314 validateState(ImmutableMap.of(
315 f1, FlowEntryState.PENDING_REMOVE,
316 f2, FlowEntryState.PENDING_REMOVE,
317 f3, FlowEntryState.ADDED)));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700318
alshabib1c319ff2014-10-04 20:29:09 -0700319 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700320 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700321 }
322
323 @Test
324 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700325 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700326 FlowRule f2 = addFlowRule(2);
Yuta HIGUCHIf6f50a62014-10-19 15:58:49 -0700327 StoredFlowEntry fe1 = new DefaultFlowEntry(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700328 FlowEntry fe2 = new DefaultFlowEntry(f2);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800329
alshabib1c319ff2014-10-04 20:29:09 -0700330 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700331 service.removeFlowRules(f1);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800332
Brian O'Connora3e5cd52015-12-05 15:59:19 -0800333 //FIXME modification of "stored" flow entry outside of store
alshabib1c319ff2014-10-04 20:29:09 -0700334 fe1.setState(FlowEntryState.REMOVED);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800335
alshabib1c319ff2014-10-04 20:29:09 -0700336 providerService.flowRemoved(fe1);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800337
alshabib3d643ec2014-10-22 18:33:00 -0700338 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED,
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800339 RULE_ADDED, RULE_REMOVE_REQUESTED, RULE_REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700340
alshabib1c319ff2014-10-04 20:29:09 -0700341 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700342 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700343
alshabibba5ac482014-10-02 17:15:20 -0700344 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700345 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700346 service.applyFlowRules(f3);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800347
alshabib1c319ff2014-10-04 20:29:09 -0700348 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
Charles Chan93fa7272016-01-26 22:27:02 -0800349 validateEvents(RULE_ADD_REQUESTED, RULE_ADDED, RULE_UPDATED);
alshabibba5ac482014-10-02 17:15:20 -0700350
alshabib1c319ff2014-10-04 20:29:09 -0700351 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700352 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700353 }
354
alshabibbb8b1282014-09-22 17:00:18 -0700355 @Test
356 public void flowMetrics() {
357 FlowRule f1 = flowRule(1, 1);
358 FlowRule f2 = flowRule(2, 2);
359 FlowRule f3 = flowRule(3, 3);
360
alshabibba5ac482014-10-02 17:15:20 -0700361 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700362
alshabib1c319ff2014-10-04 20:29:09 -0700363 FlowEntry fe1 = new DefaultFlowEntry(f1);
364 FlowEntry fe2 = new DefaultFlowEntry(f2);
365
alshabib1c319ff2014-10-04 20:29:09 -0700366 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
367 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
368
369 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700370
371 assertTrue("Entries should be added.",
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700372 validateState(ImmutableMap.of(
373 f1, FlowEntryState.ADDED,
374 f2, FlowEntryState.ADDED,
375 f3, FlowEntryState.PENDING_ADD)));
alshabibbb42cad2014-09-25 11:43:05 -0700376
alshabib3d643ec2014-10-22 18:33:00 -0700377 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
Sivachidambaram Subramanian605104e2017-06-21 07:40:04 +0530378 RULE_ADDED, RULE_ADDED, RULE_ADD_REQUESTED);
alshabibbb42cad2014-09-25 11:43:05 -0700379 }
380
381 @Test
382 public void extraneousFlow() {
383 FlowRule f1 = flowRule(1, 1);
384 FlowRule f2 = flowRule(2, 2);
385 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700386 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700387
alshabib1c319ff2014-10-04 20:29:09 -0700388// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
389// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
390// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
391 FlowEntry fe1 = new DefaultFlowEntry(f1);
392 FlowEntry fe2 = new DefaultFlowEntry(f2);
393 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700394
alshabib1c319ff2014-10-04 20:29:09 -0700395
396 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700397
alshabib3d643ec2014-10-22 18:33:00 -0700398 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700399
400 }
401
402 /*
403 * Tests whether a rule that was marked for removal but no flowRemoved was received
404 * is indeed removed at the next stats update.
405 */
406 @Test
407 public void flowMissingRemove() {
408 FlowRule f1 = flowRule(1, 1);
409 FlowRule f2 = flowRule(2, 2);
410 FlowRule f3 = flowRule(3, 3);
411
alshabib1c319ff2014-10-04 20:29:09 -0700412// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
413// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
414
415 FlowEntry fe1 = new DefaultFlowEntry(f1);
416 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700417 mgr.applyFlowRules(f1, f2, f3);
418
419 mgr.removeFlowRules(f3);
420
alshabib1c319ff2014-10-04 20:29:09 -0700421 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700422
alshabib3d643ec2014-10-22 18:33:00 -0700423 validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
424 RULE_REMOVE_REQUESTED, RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700425
426 }
427
428 @Test
429 public void getByAppId() {
430 FlowRule f1 = flowRule(1, 1);
431 FlowRule f2 = flowRule(2, 2);
432 mgr.applyFlowRules(f1, f2);
433
434 assertTrue("should have two rules",
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800435 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
alshabibbb42cad2014-09-25 11:43:05 -0700436 }
437
438 @Test
439 public void removeByAppId() {
440 FlowRule f1 = flowRule(1, 1);
441 FlowRule f2 = flowRule(2, 2);
442 mgr.applyFlowRules(f1, f2);
443
444
445 mgr.removeFlowRulesById(appId);
446
447 //only check that we are in pending remove. Events and actual remove state will
448 // be set by flowRemoved call.
Yuta HIGUCHI605347c2014-10-17 21:05:23 -0700449 validateState(ImmutableMap.of(
Thomas Vachuskae0f804a2014-10-27 23:40:48 -0700450 f1, FlowEntryState.PENDING_REMOVE,
451 f2, FlowEntryState.PENDING_REMOVE));
alshabibbb8b1282014-09-22 17:00:18 -0700452 }
453
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800454 @Test
455 public void fallbackBasics() {
456 FlowRule f1 = flowRule(FOO_DID, 1, 1);
457 flowRules.clear();
458 mgr.applyFlowRules(f1);
459 assertTrue("flow rule not applied", flowRules.contains(f1));
460
461 flowRules.clear();
462 mgr.removeFlowRules(f1);
463 assertTrue("flow rule not removed", flowRules.contains(f1));
464 }
465
466 @Test
467 public void fallbackFlowRemoved() {
468 FlowRule f1 = flowRule(FOO_DID, 1, 1);
469 mgr.applyFlowRules(f1);
470 flowRules.clear();
471 providerService.flowRemoved(new DefaultFlowEntry(f1));
472 assertTrue("flow rule not reapplied", flowRules.contains(f1));
473 }
474
475 @Test
476 public void fallbackExtraFlow() {
477 FlowRule f1 = flowRule(FOO_DID, 1, 1);
478 flowRules.clear();
479 providerService.pushFlowMetrics(FOO_DID, ImmutableList.of(new DefaultFlowEntry(f1)));
480 assertTrue("flow rule not removed", flowRules.contains(f1));
481 }
482
483 @Test
484 public void fallbackPoll() {
485 FlowRuleDriverProvider fallback = (FlowRuleDriverProvider) mgr.defaultProvider();
486 FlowRule f1 = flowRule(FOO_DID, 1, 1);
487 mgr.applyFlowRules(f1);
488 FlowEntry fe = mgr.getFlowEntries(FOO_DID).iterator().next();
489 assertEquals("incorrect state", FlowEntryState.PENDING_ADD, fe.state());
490
491 fallback.init(fallback.providerService, mgr.deviceService, mgr.mastershipService, 1);
492 TestTools.assertAfter(2000, () -> {
493 FlowEntry e = mgr.getFlowEntries(FOO_DID).iterator().next();
494 assertEquals("incorrect state", FlowEntryState.ADDED, e.state());
495 });
496 }
497
498
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700499 private static class TestListener implements FlowRuleListener {
500 final List<FlowRuleEvent> events = new ArrayList<>();
501
502 @Override
503 public void event(FlowRuleEvent event) {
504 events.add(event);
505 }
506 }
507
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800508 private static class TestDeviceService extends DeviceServiceAdapter {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700509 @Override
510 public int getDeviceCount() {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800511 return 2;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700512 }
513
514 @Override
515 public Iterable<Device> getDevices() {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800516 return ImmutableList.of(DEV, FOO_DEV);
517 }
518
519 @Override
520 public Iterable<Device> getAvailableDevices() {
521 return getDevices();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700522 }
523
524 @Override
525 public Device getDevice(DeviceId deviceId) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800526 return deviceId.equals(FOO_DID) ? FOO_DEV : DEV;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700527 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700528 }
529
530 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
531
532 protected TestProvider(ProviderId id) {
533 super(PID);
534 }
535
536 @Override
537 public void applyFlowRule(FlowRule... flowRules) {
538 }
539
540 @Override
541 public void removeFlowRule(FlowRule... flowRules) {
542 }
543
alshabiba68eb962014-09-24 20:34:13 -0700544 @Override
545 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
546 }
547
alshabib902d41b2014-10-07 16:52:05 -0700548 @Override
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800549 public void executeBatch(FlowRuleBatchOperation batch) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800550 // TODO: need to call batchOperationComplete
alshabib902d41b2014-10-07 16:52:05 -0700551 }
552
alshabibcf369912014-10-13 14:16:42 -0700553 private class TestInstallationFuture
Madan Jampani117aaae2014-10-23 10:04:05 -0700554 implements ListenableFuture<CompletedBatchOperation> {
alshabibcf369912014-10-13 14:16:42 -0700555
556 @Override
557 public boolean cancel(boolean mayInterruptIfRunning) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800558 return false;
alshabibcf369912014-10-13 14:16:42 -0700559 }
560
561 @Override
562 public boolean isCancelled() {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800563 return false;
alshabibcf369912014-10-13 14:16:42 -0700564 }
565
566 @Override
567 public boolean isDone() {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800568 return true;
alshabibcf369912014-10-13 14:16:42 -0700569 }
570
571 @Override
572 public CompletedBatchOperation get()
573 throws InterruptedException, ExecutionException {
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700574 return new CompletedBatchOperation(true, Collections.emptySet(), null);
alshabibcf369912014-10-13 14:16:42 -0700575 }
576
577 @Override
578 public CompletedBatchOperation get(long timeout, TimeUnit unit)
579 throws InterruptedException,
580 ExecutionException, TimeoutException {
Sho SHIMIZU21d00692016-08-15 11:15:28 -0700581 return new CompletedBatchOperation(true, Collections.emptySet(), null);
alshabibcf369912014-10-13 14:16:42 -0700582 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700583
584 @Override
585 public void addListener(Runnable task, Executor executor) {
Yuta HIGUCHI2fcb40c2014-11-03 14:39:10 -0800586 if (isDone()) {
587 executor.execute(task);
588 }
Madan Jampani117aaae2014-10-23 10:04:05 -0700589 }
alshabibcf369912014-10-13 14:16:42 -0700590 }
alshabiba68eb962014-09-24 20:34:13 -0700591
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700592 }
593
594 private class TestSelector implements TrafficSelector {
595
596 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700597 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700598
599 public TestSelector(int val) {
600 testval = val;
601 }
602
603 @Override
alshabibba5ac482014-10-02 17:15:20 -0700604 public Set<Criterion> criteria() {
Hyunsun Moon7bfbc1c2016-04-05 16:40:43 -0700605 return Collections.emptySet();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700606 }
607
608 @Override
Jonathan Hart936c49d2014-10-23 16:38:59 -0700609 public Criterion getCriterion(
Brian O'Connorabafb502014-12-02 22:26:20 -0800610 org.onosproject.net.flow.criteria.Criterion.Type type) {
Jonathan Hart936c49d2014-10-23 16:38:59 -0700611 return null;
612 }
613
614 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700615 public int hashCode() {
616 return testval;
617 }
618
619 @Override
620 public boolean equals(Object o) {
621 if (o instanceof TestSelector) {
622 return this.testval == ((TestSelector) o).testval;
623 }
624 return false;
625 }
Jonathan Hart936c49d2014-10-23 16:38:59 -0700626
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700627 }
628
629 private class TestTreatment implements TrafficTreatment {
630
631 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700632 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700633
634 public TestTreatment(int val) {
635 testval = val;
636 }
637
638 @Override
alshabib346b5b32015-03-06 00:42:16 -0800639 public List<Instruction> deferred() {
640 return null;
641 }
642
643 @Override
644 public List<Instruction> immediate() {
645 return null;
646 }
647
648 @Override
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -0700649 public List<Instruction> allInstructions() {
650 return null;
651 }
652
653 @Override
alshabib346b5b32015-03-06 00:42:16 -0800654 public Instructions.TableTypeTransition tableTransition() {
655 return null;
656 }
657
658 @Override
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700659 public boolean clearedDeferred() {
660 return false;
alshabib346b5b32015-03-06 00:42:16 -0800661 }
662
663 @Override
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700664 public int hashCode() {
665 return testval;
666 }
667
668 @Override
669 public boolean equals(Object o) {
670 if (o instanceof TestTreatment) {
671 return this.testval == ((TestTreatment) o).testval;
672 }
673 return false;
674 }
675
Saurav Das86af8f12015-05-25 23:55:33 -0700676 @Override
677 public MetadataInstruction writeMetadata() {
678 return null;
679 }
680
alshabib10c810b2015-08-18 16:59:04 -0700681 @Override
Cem Türker3baff672017-10-12 15:09:01 +0300682 public Instructions.StatTriggerInstruction statTrigger() {
683 return null;
684 }
685
686 @Override
alshabib10c810b2015-08-18 16:59:04 -0700687 public Instructions.MeterInstruction metered() {
688 return null;
689 }
690
cansu.toprak409289d2017-10-27 10:04:05 +0300691 @Override
692 public Set<Instructions.MeterInstruction> meters() {
693 return Sets.newHashSet();
694 }
695
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700696 }
697
alshabib92c65ad2014-10-08 21:56:05 -0700698 public class TestApplicationId extends DefaultApplicationId {
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800699 public TestApplicationId(int id, String name) {
alshabib92c65ad2014-10-08 21:56:05 -0700700 super(id, name);
701 }
702 }
703
Ray Milkeycc53abd2015-02-19 12:31:33 -0800704 private class TestCoreService extends CoreServiceAdapter {
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800705
706 @Override
707 public IdGenerator getIdGenerator(String topic) {
708 return new IdGenerator() {
709 private AtomicLong counter = new AtomicLong(0);
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800710
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800711 @Override
712 public long getNewId() {
713 return counter.getAndIncrement();
714 }
715 };
716 }
717 }
718
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800719 private class TestMastershipService extends MastershipServiceAdapter {
720 @Override
721 public MastershipRole getLocalRole(DeviceId deviceId) {
722 return MastershipRole.MASTER;
723 }
pier7aceddf2019-12-19 16:04:23 +0100724
725 @Override
726 public NodeId getMasterFor(DeviceId deviceId) {
727 return new NodeId(NODE_ID);
728 }
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800729 }
730
731 private class TestDriverManager extends DriverManager {
Thomas Vachuska11b99fc2017-04-27 12:51:04 -0700732 TestDriverManager(DriverRegistry registry) {
733 this.registry = registry;
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800734 this.deviceService = mgr.deviceService;
735 activate();
736 }
737 }
738
739 static Collection<FlowRule> flowRules = new HashSet<>();
740
741 public static class TestFlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
742
743 @Override
744 public Collection<FlowEntry> getFlowEntries() {
745 ImmutableList.Builder<FlowEntry> builder = ImmutableList.builder();
746 flowRules.stream().map(DefaultFlowEntry::new).forEach(builder::add);
747 return builder.build();
748 }
749
750 @Override
751 public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
752 flowRules.addAll(rules);
753 return rules;
754 }
755
756 @Override
757 public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
758 flowRules.addAll(rules);
759 return rules;
760 }
761 }
pier7aceddf2019-12-19 16:04:23 +0100762
763 private static class MockControllerNode implements ControllerNode {
764 final NodeId id;
765
766 public MockControllerNode(NodeId id) {
767 this.id = id;
768 }
769
770 @Override
771 public NodeId id() {
772 return this.id;
773 }
774
775 @Override
776 public Ip4Address ip() {
777 return Ip4Address.valueOf("127.0.0.1");
778 }
779
780 @Override
781 public int tcpPort() {
782 return 0;
783 }
784 }
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700785}