blob: 8d8232026a0a38deae8e1d5596fb9fbf33660f94 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.flow.impl;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -07002
3import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertFalse;
5import static org.junit.Assert.assertNotNull;
6import static org.junit.Assert.assertTrue;
alshabib97044902014-09-18 14:52:16 -07007import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
8import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
alshabib219ebaa2014-09-22 15:41:24 -07009import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070010
11import java.util.ArrayList;
12import java.util.List;
13
14import org.junit.After;
15import org.junit.Before;
16import org.junit.Test;
17import org.onlab.onos.event.impl.TestEventDispatcher;
18import org.onlab.onos.net.DefaultDevice;
19import org.onlab.onos.net.Device;
20import org.onlab.onos.net.Device.Type;
21import org.onlab.onos.net.DeviceId;
22import org.onlab.onos.net.MastershipRole;
23import org.onlab.onos.net.Port;
24import org.onlab.onos.net.PortNumber;
25import org.onlab.onos.net.device.DeviceListener;
26import org.onlab.onos.net.device.DeviceService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070027import org.onlab.onos.net.flow.DefaultFlowRule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070028import org.onlab.onos.net.flow.FlowRule;
alshabibbb8b1282014-09-22 17:00:18 -070029import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070030import org.onlab.onos.net.flow.FlowRuleEvent;
31import org.onlab.onos.net.flow.FlowRuleListener;
32import org.onlab.onos.net.flow.FlowRuleProvider;
33import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
34import org.onlab.onos.net.flow.FlowRuleProviderService;
35import org.onlab.onos.net.flow.FlowRuleService;
36import org.onlab.onos.net.flow.TrafficSelector;
37import org.onlab.onos.net.flow.TrafficTreatment;
38import org.onlab.onos.net.flow.criteria.Criterion;
39import org.onlab.onos.net.flow.instructions.Instruction;
40import org.onlab.onos.net.provider.AbstractProvider;
41import org.onlab.onos.net.provider.ProviderId;
alshabib219ebaa2014-09-22 15:41:24 -070042import org.onlab.onos.net.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070043
44import com.google.common.collect.Lists;
45import com.google.common.collect.Sets;
46
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070047/**
48 * Test codifying the flow rule service & flow rule provider service contracts.
49 */
tom202175a2014-09-19 19:00:11 -070050public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070051
tomf6ab2152014-09-18 12:08:29 -070052 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070053 private static final DeviceId DID = DeviceId.deviceId("of:001");
54 private static final Device DEV = new DefaultDevice(
55 PID, DID, Type.SWITCH, "", "", "", "");
56
tom202175a2014-09-19 19:00:11 -070057 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070058
59 protected FlowRuleService service;
60 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070061 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070062 protected TestProvider provider;
63 protected TestListener listener = new TestListener();
64
65 @Before
66 public void setUp() {
tom202175a2014-09-19 19:00:11 -070067 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070068 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070069 mgr.eventDispatcher = new TestEventDispatcher();
70 mgr.deviceService = new TestDeviceService();
71 service = mgr;
72 registry = mgr;
73
74 mgr.activate();
75 mgr.addListener(listener);
76 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -070077 providerService = registry.register(provider);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070078 assertTrue("provider should be registered",
79 registry.getProviders().contains(provider.id()));
80 }
81
82 @After
83 public void tearDown() {
84 registry.unregister(provider);
85 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -070086 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070087 service.removeListener(listener);
88 mgr.deactivate();
89 mgr.eventDispatcher = null;
90 mgr.deviceService = null;
91 }
92
93 private FlowRule flowRule(int tsval, int trval) {
94 TestSelector ts = new TestSelector(tsval);
95 TestTreatment tr = new TestTreatment(trval);
Ayaka Koshibed4e53e12014-09-18 14:24:55 -070096 return new DefaultFlowRule(DID, ts, tr, 0);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070097 }
98
alshabibbb8b1282014-09-22 17:00:18 -070099 private FlowRule flowRule(FlowRule rule, FlowRuleState state) {
100 return new DefaultFlowRule(rule, state);
101 }
102
103 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700104 FlowRule rule = flowRule(hval, hval);
alshabibbb8b1282014-09-22 17:00:18 -0700105 providerService.flowAdded(rule);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700106 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700107 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700108 }
109
110 private void validateEvents(FlowRuleEvent.Type ... events) {
111 if (events == null) {
112 assertTrue("events generated", listener.events.isEmpty());
113 }
114
115 int i = 0;
116 for (FlowRuleEvent e : listener.events) {
117 assertTrue("unexpected event", e.type().equals(events[i]));
118 i++;
119 }
120
121 assertEquals("mispredicted number of events",
122 events.length, listener.events.size());
123
124 listener.events.clear();
125 }
126
127 private int flowCount() {
128 return Sets.newHashSet(service.getFlowEntries(DID)).size();
129 }
130 @Test
131 public void getFlowEntries() {
132 assertTrue("store should be empty",
133 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
134 addFlowRule(1);
135 addFlowRule(2);
136 assertEquals("2 rules should exist", 2, flowCount());
137 validateEvents(RULE_ADDED, RULE_ADDED);
138
139 addFlowRule(1);
140 assertEquals("should still be 2 rules", 2, flowCount());
alshabib219ebaa2014-09-22 15:41:24 -0700141 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700142 }
143
alshabibbb8b1282014-09-22 17:00:18 -0700144
145 //backing store is sensitive to the order of additions/removals
146 private boolean validateState(FlowRuleState... state) {
147 Iterable<FlowRule> rules = service.getFlowEntries(DID);
148 int i = 0;
149 for (FlowRule f : rules) {
150 if (f.state() != state[i]) {
151 return false;
152 }
153 i++;
154 }
155 return true;
156 }
157
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700158 @Test
159 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700160
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700161 FlowRule r1 = flowRule(1, 1);
162 FlowRule r2 = flowRule(1, 2);
163 FlowRule r3 = flowRule(1, 3);
164
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700165 assertTrue("store should be empty",
166 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700167 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700168 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700169 assertTrue("Entries should be pending add.",
170 validateState(FlowRuleState.PENDING_ADD, FlowRuleState.PENDING_ADD,
171 FlowRuleState.PENDING_ADD));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700172 }
173
174 @Test
175 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700176 FlowRule f1 = addFlowRule(1);
177 FlowRule f2 = addFlowRule(2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700178 addFlowRule(3);
179 assertEquals("3 rules should exist", 3, flowCount());
180 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
181
alshabibbb8b1282014-09-22 17:00:18 -0700182 FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED);
183 FlowRule rem2 = flowRule(f2, FlowRuleState.REMOVED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700184 mgr.removeFlowRules(rem1, rem2);
185 //removing from north, so no events generated
186 validateEvents();
alshabib219ebaa2014-09-22 15:41:24 -0700187 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700188 assertTrue("Entries should be pending remove.",
189 validateState(FlowRuleState.CREATED, FlowRuleState.PENDING_REMOVE,
190 FlowRuleState.PENDING_REMOVE));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700191
192 mgr.removeFlowRules(rem1);
alshabib219ebaa2014-09-22 15:41:24 -0700193 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700194 }
195
196 @Test
197 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700198 FlowRule f1 = addFlowRule(1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700199 addFlowRule(2);
alshabibbb8b1282014-09-22 17:00:18 -0700200 FlowRule rem1 = flowRule(f1, FlowRuleState.REMOVED);
201 providerService.flowRemoved(rem1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700202 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
203
alshabibbb8b1282014-09-22 17:00:18 -0700204 providerService.flowRemoved(rem1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700205 validateEvents();
206 }
207
alshabibbb8b1282014-09-22 17:00:18 -0700208 @Test
209 public void flowMetrics() {
210 FlowRule f1 = flowRule(1, 1);
211 FlowRule f2 = flowRule(2, 2);
212 FlowRule f3 = flowRule(3, 3);
213
214 FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
215 FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
216 mgr.applyFlowRules(f1, f2, f3);
217
218 providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2));
219
220 assertTrue("Entries should be added.",
221 validateState(FlowRuleState.PENDING_ADD, FlowRuleState.ADDED,
222 FlowRuleState.ADDED));
223 //TODO: add tests for flowmissing and extraneous flows
224 }
225
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700226 private static class TestListener implements FlowRuleListener {
227 final List<FlowRuleEvent> events = new ArrayList<>();
228
229 @Override
230 public void event(FlowRuleEvent event) {
231 events.add(event);
232 }
233 }
234
235 private static class TestDeviceService implements DeviceService {
236
237 @Override
238 public int getDeviceCount() {
239 return 0;
240 }
241
242 @Override
243 public Iterable<Device> getDevices() {
244 return null;
245 }
246
247 @Override
248 public Device getDevice(DeviceId deviceId) {
249 return DEV;
250 }
251
252 @Override
253 public MastershipRole getRole(DeviceId deviceId) {
254 return null;
255 }
256
257 @Override
258 public List<Port> getPorts(DeviceId deviceId) {
259 return null;
260 }
261
262 @Override
263 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
264 return null;
265 }
266
267 @Override
268 public boolean isAvailable(DeviceId deviceId) {
269 return false;
270 }
271
272 @Override
273 public void addListener(DeviceListener listener) {
274 }
275
276 @Override
277 public void removeListener(DeviceListener listener) {
278 }
279
280 }
281
282 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
283
284 protected TestProvider(ProviderId id) {
285 super(PID);
286 }
287
288 @Override
289 public void applyFlowRule(FlowRule... flowRules) {
290 }
291
292 @Override
293 public void removeFlowRule(FlowRule... flowRules) {
294 }
295
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700296 }
297
298 private class TestSelector implements TrafficSelector {
299
300 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700301 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700302
303 public TestSelector(int val) {
304 testval = val;
305 }
306
307 @Override
308 public List<Criterion> criteria() {
309 return null;
310 }
311
312 @Override
313 public int hashCode() {
314 return testval;
315 }
316
317 @Override
318 public boolean equals(Object o) {
319 if (o instanceof TestSelector) {
320 return this.testval == ((TestSelector) o).testval;
321 }
322 return false;
323 }
324 }
325
326 private class TestTreatment implements TrafficTreatment {
327
328 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700329 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700330
331 public TestTreatment(int val) {
332 testval = val;
333 }
334
335 @Override
336 public List<Instruction> instructions() {
337 return null;
338 }
339
340 @Override
341 public int hashCode() {
342 return testval;
343 }
344
345 @Override
346 public boolean equals(Object o) {
347 if (o instanceof TestTreatment) {
348 return this.testval == ((TestTreatment) o).testval;
349 }
350 return false;
351 }
352
353 }
354
355}