blob: 86f3ddc6cb9d39de749cdc4e8e67cc2f1250e751 [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;
alshabibba5ac482014-10-02 17:15:20 -070012import java.util.Collections;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070013import java.util.List;
alshabibba5ac482014-10-02 17:15:20 -070014import java.util.Set;
alshabib902d41b2014-10-07 16:52:05 -070015import java.util.concurrent.Future;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070016
17import org.junit.After;
18import org.junit.Before;
19import org.junit.Test;
alshabiba68eb962014-09-24 20:34:13 -070020import org.onlab.onos.ApplicationId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070021import org.onlab.onos.event.impl.TestEventDispatcher;
22import org.onlab.onos.net.DefaultDevice;
23import org.onlab.onos.net.Device;
24import org.onlab.onos.net.Device.Type;
25import org.onlab.onos.net.DeviceId;
26import org.onlab.onos.net.MastershipRole;
27import org.onlab.onos.net.Port;
28import org.onlab.onos.net.PortNumber;
29import org.onlab.onos.net.device.DeviceListener;
30import org.onlab.onos.net.device.DeviceService;
alshabib1c319ff2014-10-04 20:29:09 -070031import org.onlab.onos.net.flow.DefaultFlowEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070032import org.onlab.onos.net.flow.DefaultFlowRule;
alshabib1c319ff2014-10-04 20:29:09 -070033import org.onlab.onos.net.flow.FlowEntry;
34import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070035import org.onlab.onos.net.flow.FlowRule;
alshabib902d41b2014-10-07 16:52:05 -070036import org.onlab.onos.net.flow.FlowRuleBatchEntry;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070037import org.onlab.onos.net.flow.FlowRuleEvent;
38import org.onlab.onos.net.flow.FlowRuleListener;
39import org.onlab.onos.net.flow.FlowRuleProvider;
40import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
41import org.onlab.onos.net.flow.FlowRuleProviderService;
42import org.onlab.onos.net.flow.FlowRuleService;
43import org.onlab.onos.net.flow.TrafficSelector;
44import org.onlab.onos.net.flow.TrafficTreatment;
45import org.onlab.onos.net.flow.criteria.Criterion;
46import org.onlab.onos.net.flow.instructions.Instruction;
alshabib902d41b2014-10-07 16:52:05 -070047import org.onlab.onos.net.intent.BatchOperation;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070048import org.onlab.onos.net.provider.AbstractProvider;
49import org.onlab.onos.net.provider.ProviderId;
tomea961ff2014-10-01 12:45:15 -070050import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070051
alshabibba5ac482014-10-02 17:15:20 -070052import com.google.common.collect.ImmutableList;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070053import com.google.common.collect.Lists;
54import com.google.common.collect.Sets;
55
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070056/**
57 * Test codifying the flow rule service & flow rule provider service contracts.
58 */
tom202175a2014-09-19 19:00:11 -070059public class FlowRuleManagerTest {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070060
tomf6ab2152014-09-18 12:08:29 -070061 private static final ProviderId PID = new ProviderId("of", "foo");
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070062 private static final DeviceId DID = DeviceId.deviceId("of:001");
alshabibba5ac482014-10-02 17:15:20 -070063 private static final int TIMEOUT = 10;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070064 private static final Device DEV = new DefaultDevice(
65 PID, DID, Type.SWITCH, "", "", "", "");
66
tom202175a2014-09-19 19:00:11 -070067 private FlowRuleManager mgr;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070068
69 protected FlowRuleService service;
70 protected FlowRuleProviderRegistry registry;
alshabibbb8b1282014-09-22 17:00:18 -070071 protected FlowRuleProviderService providerService;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070072 protected TestProvider provider;
73 protected TestListener listener = new TestListener();
alshabiba68eb962014-09-24 20:34:13 -070074 private ApplicationId appId;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070075
76 @Before
77 public void setUp() {
tom202175a2014-09-19 19:00:11 -070078 mgr = new FlowRuleManager();
tombe988312014-09-19 18:38:47 -070079 mgr.store = new SimpleFlowRuleStore();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070080 mgr.eventDispatcher = new TestEventDispatcher();
81 mgr.deviceService = new TestDeviceService();
82 service = mgr;
83 registry = mgr;
84
85 mgr.activate();
86 mgr.addListener(listener);
87 provider = new TestProvider(PID);
alshabibbb8b1282014-09-22 17:00:18 -070088 providerService = registry.register(provider);
alshabiba68eb962014-09-24 20:34:13 -070089 appId = ApplicationId.getAppId();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070090 assertTrue("provider should be registered",
91 registry.getProviders().contains(provider.id()));
92 }
93
94 @After
95 public void tearDown() {
96 registry.unregister(provider);
97 assertFalse("provider should not be registered",
alshabib97044902014-09-18 14:52:16 -070098 registry.getProviders().contains(provider.id()));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -070099 service.removeListener(listener);
100 mgr.deactivate();
101 mgr.eventDispatcher = null;
102 mgr.deviceService = null;
103 }
104
105 private FlowRule flowRule(int tsval, int trval) {
106 TestSelector ts = new TestSelector(tsval);
107 TestTreatment tr = new TestTreatment(trval);
alshabiba0e04982014-10-03 13:03:19 -0700108 return new DefaultFlowRule(DID, ts, tr, 10, appId, TIMEOUT);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700109 }
110
alshabibbb8b1282014-09-22 17:00:18 -0700111
112 private FlowRule addFlowRule(int hval) {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700113 FlowRule rule = flowRule(hval, hval);
alshabibba5ac482014-10-02 17:15:20 -0700114 service.applyFlowRules(rule);
115
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700116 assertNotNull("rule should be found", service.getFlowEntries(DID));
alshabibbb8b1282014-09-22 17:00:18 -0700117 return rule;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700118 }
119
120 private void validateEvents(FlowRuleEvent.Type ... events) {
121 if (events == null) {
122 assertTrue("events generated", listener.events.isEmpty());
123 }
124
125 int i = 0;
alshabibbb42cad2014-09-25 11:43:05 -0700126 System.err.println("events :" + listener.events);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700127 for (FlowRuleEvent e : listener.events) {
128 assertTrue("unexpected event", e.type().equals(events[i]));
129 i++;
130 }
131
132 assertEquals("mispredicted number of events",
133 events.length, listener.events.size());
134
135 listener.events.clear();
136 }
137
138 private int flowCount() {
139 return Sets.newHashSet(service.getFlowEntries(DID)).size();
140 }
141 @Test
142 public void getFlowEntries() {
143 assertTrue("store should be empty",
144 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabibba5ac482014-10-02 17:15:20 -0700145 FlowRule f1 = addFlowRule(1);
146 FlowRule f2 = addFlowRule(2);
147
alshabib1c319ff2014-10-04 20:29:09 -0700148 FlowEntry fe1 = new DefaultFlowEntry(f1);
149 FlowEntry fe2 = new DefaultFlowEntry(f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700150 assertEquals("2 rules should exist", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700151
alshabib1c319ff2014-10-04 20:29:09 -0700152 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700153 validateEvents(RULE_ADDED, RULE_ADDED);
154
155 addFlowRule(1);
156 assertEquals("should still be 2 rules", 2, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700157
alshabib1c319ff2014-10-04 20:29:09 -0700158 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
alshabib219ebaa2014-09-22 15:41:24 -0700159 validateEvents(RULE_UPDATED);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700160 }
161
alshabibbb8b1282014-09-22 17:00:18 -0700162
163 //backing store is sensitive to the order of additions/removals
alshabib1c319ff2014-10-04 20:29:09 -0700164 private boolean validateState(FlowEntryState... state) {
165 Iterable<FlowEntry> rules = service.getFlowEntries(DID);
alshabibbb8b1282014-09-22 17:00:18 -0700166 int i = 0;
alshabib1c319ff2014-10-04 20:29:09 -0700167 for (FlowEntry f : rules) {
alshabibbb8b1282014-09-22 17:00:18 -0700168 if (f.state() != state[i]) {
169 return false;
170 }
171 i++;
172 }
173 return true;
174 }
175
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700176 @Test
177 public void applyFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700178
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700179 FlowRule r1 = flowRule(1, 1);
alshabiba68eb962014-09-24 20:34:13 -0700180 FlowRule r2 = flowRule(2, 2);
181 FlowRule r3 = flowRule(3, 3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700182
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700183 assertTrue("store should be empty",
184 Sets.newHashSet(service.getFlowEntries(DID)).isEmpty());
alshabib219ebaa2014-09-22 15:41:24 -0700185 mgr.applyFlowRules(r1, r2, r3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700186 assertEquals("3 rules should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700187 assertTrue("Entries should be pending add.",
alshabib1c319ff2014-10-04 20:29:09 -0700188 validateState(FlowEntryState.PENDING_ADD, FlowEntryState.PENDING_ADD,
189 FlowEntryState.PENDING_ADD));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700190 }
191
192 @Test
193 public void removeFlowRules() {
alshabibbb8b1282014-09-22 17:00:18 -0700194 FlowRule f1 = addFlowRule(1);
195 FlowRule f2 = addFlowRule(2);
alshabibba5ac482014-10-02 17:15:20 -0700196 FlowRule f3 = addFlowRule(3);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700197 assertEquals("3 rules should exist", 3, flowCount());
alshabibba5ac482014-10-02 17:15:20 -0700198
alshabib1c319ff2014-10-04 20:29:09 -0700199 FlowEntry fe1 = new DefaultFlowEntry(f1);
200 FlowEntry fe2 = new DefaultFlowEntry(f2);
201 FlowEntry fe3 = new DefaultFlowEntry(f3);
202 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700203 validateEvents(RULE_ADDED, RULE_ADDED, RULE_ADDED);
204
alshabib1c319ff2014-10-04 20:29:09 -0700205 mgr.removeFlowRules(f1, f2);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700206 //removing from north, so no events generated
207 validateEvents();
alshabib219ebaa2014-09-22 15:41:24 -0700208 assertEquals("3 rule should exist", 3, flowCount());
alshabibbb8b1282014-09-22 17:00:18 -0700209 assertTrue("Entries should be pending remove.",
alshabib1c319ff2014-10-04 20:29:09 -0700210 validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_REMOVE,
211 FlowEntryState.ADDED));
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700212
alshabib1c319ff2014-10-04 20:29:09 -0700213 mgr.removeFlowRules(f1);
alshabib219ebaa2014-09-22 15:41:24 -0700214 assertEquals("3 rule should still exist", 3, flowCount());
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700215 }
216
217 @Test
218 public void flowRemoved() {
alshabibbb8b1282014-09-22 17:00:18 -0700219 FlowRule f1 = addFlowRule(1);
alshabibba5ac482014-10-02 17:15:20 -0700220 FlowRule f2 = addFlowRule(2);
alshabib1c319ff2014-10-04 20:29:09 -0700221 FlowEntry fe1 = new DefaultFlowEntry(f1);
222 FlowEntry fe2 = new DefaultFlowEntry(f2);
223 providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2));
alshabiba68eb962014-09-24 20:34:13 -0700224 service.removeFlowRules(f1);
alshabib1c319ff2014-10-04 20:29:09 -0700225 fe1.setState(FlowEntryState.REMOVED);
226 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700227 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
228
alshabib1c319ff2014-10-04 20:29:09 -0700229 providerService.flowRemoved(fe1);
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700230 validateEvents();
alshabibbb42cad2014-09-25 11:43:05 -0700231
alshabibba5ac482014-10-02 17:15:20 -0700232 FlowRule f3 = flowRule(3, 3);
alshabib1c319ff2014-10-04 20:29:09 -0700233 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibba5ac482014-10-02 17:15:20 -0700234 service.applyFlowRules(f3);
alshabib1c319ff2014-10-04 20:29:09 -0700235 providerService.pushFlowMetrics(DID, Collections.singletonList(fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700236 validateEvents(RULE_ADDED);
alshabibba5ac482014-10-02 17:15:20 -0700237
alshabib1c319ff2014-10-04 20:29:09 -0700238 providerService.flowRemoved(fe3);
alshabibbb42cad2014-09-25 11:43:05 -0700239 validateEvents();
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700240 }
241
alshabibbb8b1282014-09-22 17:00:18 -0700242 @Test
243 public void flowMetrics() {
244 FlowRule f1 = flowRule(1, 1);
245 FlowRule f2 = flowRule(2, 2);
246 FlowRule f3 = flowRule(3, 3);
247
alshabibba5ac482014-10-02 17:15:20 -0700248 mgr.applyFlowRules(f1, f2, f3);
alshabibbb8b1282014-09-22 17:00:18 -0700249
alshabib1c319ff2014-10-04 20:29:09 -0700250 FlowEntry fe1 = new DefaultFlowEntry(f1);
251 FlowEntry fe2 = new DefaultFlowEntry(f2);
252
253
254 //FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
255 //FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
256
257 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb8b1282014-09-22 17:00:18 -0700258
259 assertTrue("Entries should be added.",
alshabib1c319ff2014-10-04 20:29:09 -0700260 validateState(FlowEntryState.ADDED, FlowEntryState.ADDED,
261 FlowEntryState.PENDING_ADD));
alshabibbb42cad2014-09-25 11:43:05 -0700262
alshabibba5ac482014-10-02 17:15:20 -0700263 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700264 }
265
266 @Test
267 public void extraneousFlow() {
268 FlowRule f1 = flowRule(1, 1);
269 FlowRule f2 = flowRule(2, 2);
270 FlowRule f3 = flowRule(3, 3);
alshabibba5ac482014-10-02 17:15:20 -0700271 mgr.applyFlowRules(f1, f2);
alshabibbb42cad2014-09-25 11:43:05 -0700272
alshabib1c319ff2014-10-04 20:29:09 -0700273// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
274// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
275// FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
276 FlowEntry fe1 = new DefaultFlowEntry(f1);
277 FlowEntry fe2 = new DefaultFlowEntry(f2);
278 FlowEntry fe3 = new DefaultFlowEntry(f3);
alshabibbb42cad2014-09-25 11:43:05 -0700279
alshabib1c319ff2014-10-04 20:29:09 -0700280
281 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2, fe3));
alshabibbb42cad2014-09-25 11:43:05 -0700282
alshabibba5ac482014-10-02 17:15:20 -0700283 validateEvents(RULE_ADDED, RULE_ADDED);
alshabibbb42cad2014-09-25 11:43:05 -0700284
285 }
286
287 /*
288 * Tests whether a rule that was marked for removal but no flowRemoved was received
289 * is indeed removed at the next stats update.
290 */
291 @Test
292 public void flowMissingRemove() {
293 FlowRule f1 = flowRule(1, 1);
294 FlowRule f2 = flowRule(2, 2);
295 FlowRule f3 = flowRule(3, 3);
296
alshabib1c319ff2014-10-04 20:29:09 -0700297// FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
298// FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
299
300 FlowEntry fe1 = new DefaultFlowEntry(f1);
301 FlowEntry fe2 = new DefaultFlowEntry(f2);
alshabibbb42cad2014-09-25 11:43:05 -0700302 mgr.applyFlowRules(f1, f2, f3);
303
304 mgr.removeFlowRules(f3);
305
alshabib1c319ff2014-10-04 20:29:09 -0700306 providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
alshabibbb42cad2014-09-25 11:43:05 -0700307
alshabibba5ac482014-10-02 17:15:20 -0700308 validateEvents(RULE_ADDED, RULE_ADDED, RULE_REMOVED);
alshabibbb42cad2014-09-25 11:43:05 -0700309
310 }
311
312 @Test
313 public void getByAppId() {
314 FlowRule f1 = flowRule(1, 1);
315 FlowRule f2 = flowRule(2, 2);
316 mgr.applyFlowRules(f1, f2);
317
318 assertTrue("should have two rules",
319 Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
320 }
321
322 @Test
323 public void removeByAppId() {
324 FlowRule f1 = flowRule(1, 1);
325 FlowRule f2 = flowRule(2, 2);
326 mgr.applyFlowRules(f1, f2);
327
328
329 mgr.removeFlowRulesById(appId);
330
331 //only check that we are in pending remove. Events and actual remove state will
332 // be set by flowRemoved call.
alshabib1c319ff2014-10-04 20:29:09 -0700333 validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_REMOVE);
alshabibbb8b1282014-09-22 17:00:18 -0700334 }
335
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700336 private static class TestListener implements FlowRuleListener {
337 final List<FlowRuleEvent> events = new ArrayList<>();
338
339 @Override
340 public void event(FlowRuleEvent event) {
341 events.add(event);
342 }
343 }
344
345 private static class TestDeviceService implements DeviceService {
346
347 @Override
348 public int getDeviceCount() {
349 return 0;
350 }
351
352 @Override
353 public Iterable<Device> getDevices() {
354 return null;
355 }
356
357 @Override
358 public Device getDevice(DeviceId deviceId) {
359 return DEV;
360 }
361
362 @Override
363 public MastershipRole getRole(DeviceId deviceId) {
364 return null;
365 }
366
367 @Override
368 public List<Port> getPorts(DeviceId deviceId) {
369 return null;
370 }
371
372 @Override
373 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
374 return null;
375 }
376
377 @Override
378 public boolean isAvailable(DeviceId deviceId) {
379 return false;
380 }
381
382 @Override
383 public void addListener(DeviceListener listener) {
384 }
385
386 @Override
387 public void removeListener(DeviceListener listener) {
388 }
389
390 }
391
392 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
393
394 protected TestProvider(ProviderId id) {
395 super(PID);
396 }
397
398 @Override
399 public void applyFlowRule(FlowRule... flowRules) {
400 }
401
402 @Override
403 public void removeFlowRule(FlowRule... flowRules) {
404 }
405
alshabiba68eb962014-09-24 20:34:13 -0700406 @Override
407 public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
408 }
409
alshabib902d41b2014-10-07 16:52:05 -0700410 @Override
411 public Future<Void> executeBatch(
412 BatchOperation<FlowRuleBatchEntry> batch) {
413 // TODO Auto-generated method stub
414 return null;
415 }
416
alshabiba68eb962014-09-24 20:34:13 -0700417
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700418 }
419
420 private class TestSelector implements TrafficSelector {
421
422 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700423 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700424
425 public TestSelector(int val) {
426 testval = val;
427 }
428
429 @Override
alshabibba5ac482014-10-02 17:15:20 -0700430 public Set<Criterion> criteria() {
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700431 return null;
432 }
433
434 @Override
435 public int hashCode() {
436 return testval;
437 }
438
439 @Override
440 public boolean equals(Object o) {
441 if (o instanceof TestSelector) {
442 return this.testval == ((TestSelector) o).testval;
443 }
444 return false;
445 }
446 }
447
448 private class TestTreatment implements TrafficTreatment {
449
450 //for controlling hashcode uniqueness;
alshabib97044902014-09-18 14:52:16 -0700451 private final int testval;
Ayaka Koshibeb55524f2014-09-18 09:59:24 -0700452
453 public TestTreatment(int val) {
454 testval = val;
455 }
456
457 @Override
458 public List<Instruction> instructions() {
459 return null;
460 }
461
462 @Override
463 public int hashCode() {
464 return testval;
465 }
466
467 @Override
468 public boolean equals(Object o) {
469 if (o instanceof TestTreatment) {
470 return this.testval == ((TestTreatment) o).testval;
471 }
472 return false;
473 }
474
475 }
476
477}