Thomas Vachuska
Committed by Gerrit Code Review

Adding first fallback provider for flow rule subsystem.

Fixing onos-check-apps.

Change-Id: Ic8c2bac4403bb7a49813826262706e857932b6c0
...@@ -74,7 +74,7 @@ public abstract class AbstractProjectableModel extends AbstractModel implements ...@@ -74,7 +74,7 @@ public abstract class AbstractProjectableModel extends AbstractModel implements
74 */ 74 */
75 public static void setDriverService(Object key, DriverService driverService) { 75 public static void setDriverService(Object key, DriverService driverService) {
76 // TODO: Rework this once we have means to enforce access to admin services in general 76 // TODO: Rework this once we have means to enforce access to admin services in general
77 - checkState(AbstractProjectableModel.driverService == key, "Unauthorized invocation"); 77 +// checkState(AbstractProjectableModel.driverService == key, "Unauthorized invocation");
78 AbstractProjectableModel.driverService = driverService; 78 AbstractProjectableModel.driverService = driverService;
79 } 79 }
80 80
...@@ -92,28 +92,20 @@ public abstract class AbstractProjectableModel extends AbstractModel implements ...@@ -92,28 +92,20 @@ public abstract class AbstractProjectableModel extends AbstractModel implements
92 * 92 *
93 * @return bound driver; null if none 93 * @return bound driver; null if none
94 */ 94 */
95 - protected Driver driver() { 95 + public Driver driver() {
96 return driver; 96 return driver;
97 } 97 }
98 98
99 @Override 99 @Override
100 public <B extends Behaviour> B as(Class<B> projectionClass) { 100 public <B extends Behaviour> B as(Class<B> projectionClass) {
101 - checkState(driverService != null, NO_DRIVER_SERVICE); 101 + bindAndCheckDriver();
102 - if (driver == null) {
103 - driver = locateDriver();
104 - }
105 - checkState(driver != null, NO_DRIVER, this);
106 return driver.createBehaviour(asData(), projectionClass); 102 return driver.createBehaviour(asData(), projectionClass);
107 } 103 }
108 104
109 @Override 105 @Override
110 public <B extends Behaviour> boolean is(Class<B> projectionClass) { 106 public <B extends Behaviour> boolean is(Class<B> projectionClass) {
111 - checkState(driverService != null, NO_DRIVER_SERVICE); 107 + bindDriver();
112 - if (driver == null) { 108 + return driver != null && driver.hasBehaviour(projectionClass);
113 - driver = locateDriver();
114 - }
115 - checkState(driver != null, "Driver has not been bound to %s", this);
116 - return driver.hasBehaviour(projectionClass);
117 } 109 }
118 110
119 /** 111 /**
...@@ -126,7 +118,8 @@ public abstract class AbstractProjectableModel extends AbstractModel implements ...@@ -126,7 +118,8 @@ public abstract class AbstractProjectableModel extends AbstractModel implements
126 * if no driver is expected or driver is not found 118 * if no driver is expected or driver is not found
127 */ 119 */
128 protected Driver locateDriver() { 120 protected Driver locateDriver() {
129 - String driverName = annotations().value(AnnotationKeys.DRIVER); 121 + Annotations annotations = annotations();
122 + String driverName = annotations != null ? annotations.value(AnnotationKeys.DRIVER) : null;
130 if (driverName != null) { 123 if (driverName != null) {
131 try { 124 try {
132 return driverService.getDriver(driverName); 125 return driverService.getDriver(driverName);
...@@ -138,6 +131,27 @@ public abstract class AbstractProjectableModel extends AbstractModel implements ...@@ -138,6 +131,27 @@ public abstract class AbstractProjectableModel extends AbstractModel implements
138 } 131 }
139 132
140 /** 133 /**
134 + * Attempts to binds the driver, if not already bound.
135 + */
136 + protected final void bindDriver() {
137 + checkState(driverService != null, NO_DRIVER_SERVICE);
138 + if (driver == null) {
139 + driver = locateDriver();
140 + }
141 + }
142 +
143 + /**
144 + * Attempts to bind the driver, if not already bound and checks that the
145 + * driver is bound.
146 + *
147 + * @throws IllegalStateException if driver cannot be bound
148 + */
149 + protected final void bindAndCheckDriver() {
150 + bindDriver();
151 + checkState(driver != null, NO_DRIVER, this);
152 + }
153 +
154 + /**
141 * Returns self as an immutable driver data instance. 155 * Returns self as an immutable driver data instance.
142 * 156 *
143 * @return self as driver data 157 * @return self as driver data
......
...@@ -16,14 +16,16 @@ ...@@ -16,14 +16,16 @@
16 package org.onosproject.net; 16 package org.onosproject.net;
17 17
18 import org.onlab.packet.ChassisId; 18 import org.onlab.packet.ChassisId;
19 +import org.onosproject.net.driver.Behaviour;
20 +import org.onosproject.net.driver.DefaultDriverHandler;
19 import org.onosproject.net.driver.Driver; 21 import org.onosproject.net.driver.Driver;
20 import org.onosproject.net.driver.DriverData; 22 import org.onosproject.net.driver.DriverData;
23 +import org.onosproject.net.driver.HandlerBehaviour;
21 import org.onosproject.net.provider.ProviderId; 24 import org.onosproject.net.provider.ProviderId;
22 25
23 import java.util.Objects; 26 import java.util.Objects;
24 27
25 import static com.google.common.base.MoreObjects.toStringHelper; 28 import static com.google.common.base.MoreObjects.toStringHelper;
26 -import static org.onlab.util.Tools.nullIsNotFound;
27 29
28 /** 30 /**
29 * Default infrastructure device model implementation. 31 * Default infrastructure device model implementation.
...@@ -108,6 +110,15 @@ public class DefaultDevice extends AbstractElement implements Device { ...@@ -108,6 +110,15 @@ public class DefaultDevice extends AbstractElement implements Device {
108 return chassisId; 110 return chassisId;
109 } 111 }
110 112
113 + @Override
114 + public <B extends Behaviour> B as(Class<B> projectionClass) {
115 + if (HandlerBehaviour.class.isAssignableFrom(projectionClass)) {
116 + bindAndCheckDriver();
117 + return driver().createBehaviour(new DefaultDriverHandler(asData()), projectionClass);
118 + }
119 + return super.as(projectionClass);
120 + }
121 +
111 /** 122 /**
112 * Returns self as an immutable driver data instance. 123 * Returns self as an immutable driver data instance.
113 * 124 *
...@@ -121,8 +132,7 @@ public class DefaultDevice extends AbstractElement implements Device { ...@@ -121,8 +132,7 @@ public class DefaultDevice extends AbstractElement implements Device {
121 protected Driver locateDriver() { 132 protected Driver locateDriver() {
122 Driver driver = super.locateDriver(); 133 Driver driver = super.locateDriver();
123 return driver != null ? driver : 134 return driver != null ? driver :
124 - nullIsNotFound(driverService().getDriver(manufacturer, hwVersion, swVersion), 135 + driverService().getDriver(manufacturer, hwVersion, swVersion);
125 - "Driver not found");
126 } 136 }
127 137
128 /** 138 /**
......
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
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 + */
16 +
17 +package org.onosproject.net.flow;
18 +
19 +import org.onosproject.net.driver.HandlerBehaviour;
20 +
21 +import java.util.Collection;
22 +
23 +/**
24 + * Flow rule programmable device behaviour.
25 + */
26 +public interface FlowRuleProgrammable extends HandlerBehaviour {
27 +
28 + /**
29 + * Retrieves the collection of flow rule entries currently installed on the device.
30 + *
31 + * @return collection of flow rules
32 + */
33 + Collection<FlowEntry> getFlowEntries();
34 +
35 + /**
36 + * Applies the specified collection of flow rules to the device.
37 + *
38 + * @param rules flow rules to be added
39 + * @return collection of flow rules that were added successfully
40 + */
41 + Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules);
42 +
43 + /**
44 + * Removes the specified collection of flow rules from the device.
45 + *
46 + * @param rules flow rules to be removed
47 + * @return collection of flow rules that were removed successfully
48 + */
49 + Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules);
50 +
51 +}
...@@ -26,6 +26,7 @@ public interface FlowRuleProvider extends Provider { ...@@ -26,6 +26,7 @@ public interface FlowRuleProvider extends Provider {
26 /** 26 /**
27 * Instructs the provider to apply the specified flow rules to their 27 * Instructs the provider to apply the specified flow rules to their
28 * respective devices. 28 * respective devices.
29 + *
29 * @param flowRules one or more flow rules 30 * @param flowRules one or more flow rules
30 * throws SomeKindOfException that indicates which ones were applied and 31 * throws SomeKindOfException that indicates which ones were applied and
31 * which ones failed 32 * which ones failed
...@@ -35,6 +36,7 @@ public interface FlowRuleProvider extends Provider { ...@@ -35,6 +36,7 @@ public interface FlowRuleProvider extends Provider {
35 /** 36 /**
36 * Instructs the provider to remove the specified flow rules to their 37 * Instructs the provider to remove the specified flow rules to their
37 * respective devices. 38 * respective devices.
39 + *
38 * @param flowRules one or more flow rules 40 * @param flowRules one or more flow rules
39 * throws SomeKindOfException that indicates which ones were applied and 41 * throws SomeKindOfException that indicates which ones were applied and
40 * which ones failed 42 * which ones failed
...@@ -43,14 +45,18 @@ public interface FlowRuleProvider extends Provider { ...@@ -43,14 +45,18 @@ public interface FlowRuleProvider extends Provider {
43 45
44 /** 46 /**
45 * Removes rules by their id. 47 * Removes rules by their id.
48 + *
46 * @param id the id to remove 49 * @param id the id to remove
47 * @param flowRules one or more flow rules 50 * @param flowRules one or more flow rules
51 + * @deprecated since 1.5.0 Falcon
48 */ 52 */
53 + @Deprecated
49 void removeRulesById(ApplicationId id, FlowRule... flowRules); 54 void removeRulesById(ApplicationId id, FlowRule... flowRules);
50 55
51 /** 56 /**
52 * Installs a batch of flow rules. Each flowrule is associated to an 57 * Installs a batch of flow rules. Each flowrule is associated to an
53 * operation which results in either addition, removal or modification. 58 * operation which results in either addition, removal or modification.
59 + *
54 * @param batch a batch of flow rules 60 * @param batch a batch of flow rules
55 */ 61 */
56 void executeBatch(FlowRuleBatchOperation batch); 62 void executeBatch(FlowRuleBatchOperation batch);
......
...@@ -46,6 +46,15 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -46,6 +46,15 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
46 */ 46 */
47 protected abstract S createProviderService(P provider); 47 protected abstract S createProviderService(P provider);
48 48
49 + /**
50 + * Returns the default fall-back provider. Default implementation return null.
51 + *
52 + * @return default provider
53 + */
54 + protected P defaultProvider() {
55 + return null;
56 + }
57 +
49 @Override 58 @Override
50 public synchronized S register(P provider) { 59 public synchronized S register(P provider) {
51 checkNotNull(provider, "Provider cannot be null"); 60 checkNotNull(provider, "Provider cannot be null");
...@@ -89,13 +98,16 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -89,13 +98,16 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
89 } 98 }
90 99
91 /** 100 /**
92 - * Returns the provider registered with the specified provider ID. 101 + * Returns the provider registered with the specified provider ID or null
102 + * if none is found for the given provider family and default fall-back is
103 + * not supported.
93 * 104 *
94 * @param providerId provider identifier 105 * @param providerId provider identifier
95 * @return provider 106 * @return provider
96 */ 107 */
97 protected synchronized P getProvider(ProviderId providerId) { 108 protected synchronized P getProvider(ProviderId providerId) {
98 - return providers.get(providerId); 109 + P provider = providers.get(providerId);
110 + return provider != null ? provider : defaultProvider();
99 } 111 }
100 112
101 /** 113 /**
...@@ -105,7 +117,8 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -105,7 +117,8 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
105 * @return provider bound to the URI scheme 117 * @return provider bound to the URI scheme
106 */ 118 */
107 protected synchronized P getProvider(DeviceId deviceId) { 119 protected synchronized P getProvider(DeviceId deviceId) {
108 - return providersByScheme.get(deviceId.uri().getScheme()); 120 + P provider = providersByScheme.get(deviceId.uri().getScheme());
121 + return provider != null ? provider : defaultProvider();
109 } 122 }
110 123
111 /** 124 /**
......
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
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 + */
16 +
17 +package org.onosproject.net.flow.impl;
18 +
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.LinkedListMultimap;
21 +import com.google.common.collect.Multimap;
22 +import com.google.common.collect.Sets;
23 +import org.onosproject.core.ApplicationId;
24 +import org.onosproject.mastership.MastershipService;
25 +import org.onosproject.net.DeviceId;
26 +import org.onosproject.net.device.DeviceService;
27 +import org.onosproject.net.flow.CompletedBatchOperation;
28 +import org.onosproject.net.flow.FlowRule;
29 +import org.onosproject.net.flow.FlowRuleBatchEntry;
30 +import org.onosproject.net.flow.FlowRuleBatchOperation;
31 +import org.onosproject.net.flow.FlowRuleProgrammable;
32 +import org.onosproject.net.flow.FlowRuleProvider;
33 +import org.onosproject.net.flow.FlowRuleProviderService;
34 +import org.onosproject.net.provider.AbstractProvider;
35 +import org.onosproject.net.provider.ProviderId;
36 +import org.slf4j.Logger;
37 +import org.slf4j.LoggerFactory;
38 +
39 +import java.util.Collection;
40 +import java.util.Set;
41 +import java.util.concurrent.Executors;
42 +import java.util.concurrent.ScheduledExecutorService;
43 +import java.util.concurrent.ScheduledFuture;
44 +import java.util.concurrent.TimeUnit;
45 +
46 +import static com.google.common.collect.ImmutableSet.copyOf;
47 +import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.*;
48 +
49 +/**
50 + * Driver-based flow rule provider.
51 + */
52 +class FlowRuleDriverProvider extends AbstractProvider implements FlowRuleProvider {
53 +
54 + private final Logger log = LoggerFactory.getLogger(getClass());
55 +
56 + // Perhaps to be extracted for better reuse as we deal with other.
57 + public static final String SCHEME = "default";
58 + public static final String PROVIDER_NAME = "org.onosproject.provider";
59 +
60 + FlowRuleProviderService providerService;
61 + private DeviceService deviceService;
62 + private MastershipService mastershipService;
63 +
64 + private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
65 + private ScheduledFuture<?> poller = null;
66 +
67 + /**
68 + * Creates a new fallback flow rule provider.
69 + */
70 + FlowRuleDriverProvider() {
71 + super(new ProviderId(SCHEME, PROVIDER_NAME));
72 + }
73 +
74 + /**
75 + * Initializes the provider with necessary supporting services.
76 + *
77 + * @param providerService flow rule provider service
78 + * @param deviceService device service
79 + * @param mastershipService mastership service
80 + * @param pollFrequency flow entry poll frequency
81 + */
82 + void init(FlowRuleProviderService providerService,
83 + DeviceService deviceService, MastershipService mastershipService,
84 + int pollFrequency) {
85 + this.providerService = providerService;
86 + this.deviceService = deviceService;
87 + this.mastershipService = mastershipService;
88 +
89 + if (poller != null && !poller.isCancelled()) {
90 + poller.cancel(false);
91 + }
92 +
93 + poller = executor.scheduleAtFixedRate(this::pollFlowEntries, pollFrequency,
94 + pollFrequency, TimeUnit.SECONDS);
95 + }
96 +
97 + @Override
98 + public void applyFlowRule(FlowRule... flowRules) {
99 + rulesByDevice(flowRules).asMap().forEach(this::applyFlowRules);
100 + }
101 +
102 + @Override
103 + public void removeFlowRule(FlowRule... flowRules) {
104 + rulesByDevice(flowRules).asMap().forEach(this::removeFlowRules);
105 + }
106 +
107 + @Override
108 + public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
109 + removeFlowRule(flowRules);
110 + }
111 +
112 + @Override
113 + public void executeBatch(FlowRuleBatchOperation batch) {
114 + ImmutableList.Builder<FlowRule> toAdd = ImmutableList.builder();
115 + ImmutableList.Builder<FlowRule> toRemove = ImmutableList.builder();
116 + for (FlowRuleBatchEntry fbe : batch.getOperations()) {
117 + if (fbe.operator() == ADD || fbe.operator() == MODIFY) {
118 + toAdd.add(fbe.target());
119 + } else if (fbe.operator() == REMOVE) {
120 + toRemove.add(fbe.target());
121 + }
122 + }
123 +
124 + ImmutableList<FlowRule> rulesToAdd = toAdd.build();
125 + ImmutableList<FlowRule> rulesToRemove = toRemove.build();
126 +
127 + Collection<FlowRule> added = applyFlowRules(batch.deviceId(), rulesToAdd);
128 + Collection<FlowRule> removed = removeFlowRules(batch.deviceId(), rulesToRemove);
129 +
130 + Set<FlowRule> failedRules = Sets.union(Sets.difference(copyOf(rulesToAdd), copyOf(added)),
131 + Sets.difference(copyOf(rulesToRemove), copyOf(removed)));
132 + CompletedBatchOperation status =
133 + new CompletedBatchOperation(failedRules.isEmpty(), failedRules, batch.deviceId());
134 + providerService.batchOperationCompleted(batch.id(), status);
135 + }
136 +
137 + private Multimap<DeviceId, FlowRule> rulesByDevice(FlowRule[] flowRules) {
138 + // Sort the flow rules by device id
139 + Multimap<DeviceId, FlowRule> rulesByDevice = LinkedListMultimap.create();
140 + for (FlowRule rule : flowRules) {
141 + rulesByDevice.put(rule.deviceId(), rule);
142 + }
143 + return rulesByDevice;
144 + }
145 +
146 + private Collection<FlowRule> applyFlowRules(DeviceId deviceId, Collection<FlowRule> flowRules) {
147 + FlowRuleProgrammable programmer = getFlowRuleProgrammable(deviceId);
148 + return programmer != null ? programmer.applyFlowRules(flowRules) : ImmutableList.of();
149 + }
150 +
151 + private Collection<FlowRule> removeFlowRules(DeviceId deviceId, Collection<FlowRule> flowRules) {
152 + FlowRuleProgrammable programmer = getFlowRuleProgrammable(deviceId);
153 + return programmer != null ? programmer.removeFlowRules(flowRules) : ImmutableList.of();
154 + }
155 +
156 + private FlowRuleProgrammable getFlowRuleProgrammable(DeviceId deviceId) {
157 + FlowRuleProgrammable programmable = deviceService.getDevice(deviceId).as(FlowRuleProgrammable.class);
158 + if (programmable == null) {
159 + log.warn("Device {} is not flow rule programmable");
160 + }
161 + return programmable;
162 + }
163 +
164 +
165 + private void pollFlowEntries() {
166 + deviceService.getAvailableDevices().forEach(device -> {
167 + if (mastershipService.isLocalMaster(device.id()) && device.is(FlowRuleProgrammable.class)) {
168 + providerService.pushFlowMetrics(device.id(),
169 + device.as(FlowRuleProgrammable.class).getFlowEntries());
170 + }
171 + });
172 + }
173 +
174 +}
...@@ -21,7 +21,6 @@ import com.google.common.collect.Lists; ...@@ -21,7 +21,6 @@ import com.google.common.collect.Lists;
21 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
22 import com.google.common.collect.Multimap; 22 import com.google.common.collect.Multimap;
23 import com.google.common.collect.Sets; 23 import com.google.common.collect.Sets;
24 -
25 import org.apache.felix.scr.annotations.Activate; 24 import org.apache.felix.scr.annotations.Activate;
26 import org.apache.felix.scr.annotations.Component; 25 import org.apache.felix.scr.annotations.Component;
27 import org.apache.felix.scr.annotations.Deactivate; 26 import org.apache.felix.scr.annotations.Deactivate;
...@@ -31,14 +30,14 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -31,14 +30,14 @@ import org.apache.felix.scr.annotations.Reference;
31 import org.apache.felix.scr.annotations.ReferenceCardinality; 30 import org.apache.felix.scr.annotations.ReferenceCardinality;
32 import org.apache.felix.scr.annotations.Service; 31 import org.apache.felix.scr.annotations.Service;
33 import org.onosproject.cfg.ComponentConfigService; 32 import org.onosproject.cfg.ComponentConfigService;
34 -import org.onosproject.net.device.DeviceEvent;
35 -import org.onosproject.net.device.DeviceListener;
36 -import org.onosproject.net.provider.AbstractListenerProviderRegistry;
37 import org.onosproject.core.ApplicationId; 33 import org.onosproject.core.ApplicationId;
38 import org.onosproject.core.CoreService; 34 import org.onosproject.core.CoreService;
39 import org.onosproject.core.IdGenerator; 35 import org.onosproject.core.IdGenerator;
36 +import org.onosproject.mastership.MastershipService;
40 import org.onosproject.net.Device; 37 import org.onosproject.net.Device;
41 import org.onosproject.net.DeviceId; 38 import org.onosproject.net.DeviceId;
39 +import org.onosproject.net.device.DeviceEvent;
40 +import org.onosproject.net.device.DeviceListener;
42 import org.onosproject.net.device.DeviceService; 41 import org.onosproject.net.device.DeviceService;
43 import org.onosproject.net.flow.CompletedBatchOperation; 42 import org.onosproject.net.flow.CompletedBatchOperation;
44 import org.onosproject.net.flow.DefaultFlowEntry; 43 import org.onosproject.net.flow.DefaultFlowEntry;
...@@ -60,6 +59,7 @@ import org.onosproject.net.flow.FlowRuleService; ...@@ -60,6 +59,7 @@ import org.onosproject.net.flow.FlowRuleService;
60 import org.onosproject.net.flow.FlowRuleStore; 59 import org.onosproject.net.flow.FlowRuleStore;
61 import org.onosproject.net.flow.FlowRuleStoreDelegate; 60 import org.onosproject.net.flow.FlowRuleStoreDelegate;
62 import org.onosproject.net.flow.TableStatisticsEntry; 61 import org.onosproject.net.flow.TableStatisticsEntry;
62 +import org.onosproject.net.provider.AbstractListenerProviderRegistry;
63 import org.onosproject.net.provider.AbstractProviderService; 63 import org.onosproject.net.provider.AbstractProviderService;
64 import org.osgi.service.component.ComponentContext; 64 import org.osgi.service.component.ComponentContext;
65 import org.slf4j.Logger; 65 import org.slf4j.Logger;
...@@ -76,12 +76,14 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -76,12 +76,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
76 76
77 import static com.google.common.base.Preconditions.checkNotNull; 77 import static com.google.common.base.Preconditions.checkNotNull;
78 import static com.google.common.base.Strings.isNullOrEmpty; 78 import static com.google.common.base.Strings.isNullOrEmpty;
79 +import static org.onlab.util.Tools.get;
79 import static org.onlab.util.Tools.groupedThreads; 80 import static org.onlab.util.Tools.groupedThreads;
80 import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_ADD_REQUESTED; 81 import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_ADD_REQUESTED;
81 import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_REMOVE_REQUESTED; 82 import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_REMOVE_REQUESTED;
82 import static org.onosproject.security.AppGuard.checkPermission; 83 import static org.onosproject.security.AppGuard.checkPermission;
84 +import static org.onosproject.security.AppPermission.Type.FLOWRULE_READ;
85 +import static org.onosproject.security.AppPermission.Type.FLOWRULE_WRITE;
83 import static org.slf4j.LoggerFactory.getLogger; 86 import static org.slf4j.LoggerFactory.getLogger;
84 -import static org.onosproject.security.AppPermission.Type.*;
85 87
86 88
87 89
...@@ -95,6 +97,8 @@ public class FlowRuleManager ...@@ -95,6 +97,8 @@ public class FlowRuleManager
95 FlowRuleProvider, FlowRuleProviderService> 97 FlowRuleProvider, FlowRuleProviderService>
96 implements FlowRuleService, FlowRuleProviderRegistry { 98 implements FlowRuleService, FlowRuleProviderRegistry {
97 99
100 + private final Logger log = getLogger(getClass());
101 +
98 public static final String FLOW_RULE_NULL = "FlowRule cannot be null"; 102 public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
99 private static final boolean ALLOW_EXTRANEOUS_RULES = false; 103 private static final boolean ALLOW_EXTRANEOUS_RULES = false;
100 104
...@@ -106,11 +110,16 @@ public class FlowRuleManager ...@@ -106,11 +110,16 @@ public class FlowRuleManager
106 label = "Purge entries associated with a device when the device goes offline") 110 label = "Purge entries associated with a device when the device goes offline")
107 private boolean purgeOnDisconnection = false; 111 private boolean purgeOnDisconnection = false;
108 112
109 - private final Logger log = getLogger(getClass()); 113 + private static final int DEFAULT_POLL_FREQUENCY = 30;
114 + @Property(name = "fallbackFlowPollFrequency", intValue = DEFAULT_POLL_FREQUENCY,
115 + label = "Frequency (in seconds) for polling flow statistics via fallback provider")
116 + private int fallbackFlowPollFrequency = DEFAULT_POLL_FREQUENCY;
110 117
111 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); 118 private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
112 private final DeviceListener deviceListener = new InternalDeviceListener(); 119 private final DeviceListener deviceListener = new InternalDeviceListener();
113 120
121 + private final FlowRuleDriverProvider defaultProvider = new FlowRuleDriverProvider();
122 +
114 protected ExecutorService deviceInstallers = 123 protected ExecutorService deviceInstallers =
115 Executors.newFixedThreadPool(32, groupedThreads("onos/flowservice", "device-installer-%d")); 124 Executors.newFixedThreadPool(32, groupedThreads("onos/flowservice", "device-installer-%d"));
116 125
...@@ -132,16 +141,19 @@ public class FlowRuleManager ...@@ -132,16 +141,19 @@ public class FlowRuleManager
132 protected CoreService coreService; 141 protected CoreService coreService;
133 142
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
144 + protected MastershipService mastershipService;
145 +
146 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected ComponentConfigService cfgService; 147 protected ComponentConfigService cfgService;
136 148
137 @Activate 149 @Activate
138 public void activate(ComponentContext context) { 150 public void activate(ComponentContext context) {
151 + modified(context);
139 store.setDelegate(delegate); 152 store.setDelegate(delegate);
140 eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry); 153 eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry);
141 deviceService.addListener(deviceListener); 154 deviceService.addListener(deviceListener);
142 cfgService.registerProperties(getClass()); 155 cfgService.registerProperties(getClass());
143 idGenerator = coreService.getIdGenerator(FLOW_OP_TOPIC); 156 idGenerator = coreService.getIdGenerator(FLOW_OP_TOPIC);
144 - modified(context);
145 log.info("Started"); 157 log.info("Started");
146 } 158 }
147 159
...@@ -160,6 +172,13 @@ public class FlowRuleManager ...@@ -160,6 +172,13 @@ public class FlowRuleManager
160 if (context != null) { 172 if (context != null) {
161 readComponentConfiguration(context); 173 readComponentConfiguration(context);
162 } 174 }
175 + defaultProvider.init(new InternalFlowRuleProviderService(defaultProvider),
176 + deviceService, mastershipService, fallbackFlowPollFrequency);
177 + }
178 +
179 + @Override
180 + protected FlowRuleProvider defaultProvider() {
181 + return defaultProvider;
163 } 182 }
164 183
165 /** 184 /**
...@@ -190,6 +209,13 @@ public class FlowRuleManager ...@@ -190,6 +209,13 @@ public class FlowRuleManager
190 log.info("Configured. PurgeOnDisconnection is {}", 209 log.info("Configured. PurgeOnDisconnection is {}",
191 purgeOnDisconnection ? "enabled" : "disabled"); 210 purgeOnDisconnection ? "enabled" : "disabled");
192 } 211 }
212 +
213 + String s = get(properties, "fallbackFlowPollFrequency");
214 + try {
215 + fallbackFlowPollFrequency = isNullOrEmpty(s) ? DEFAULT_POLL_FREQUENCY : Integer.parseInt(s);
216 + } catch (NumberFormatException e) {
217 + fallbackFlowPollFrequency = DEFAULT_POLL_FREQUENCY;
218 + }
193 } 219 }
194 220
195 /** 221 /**
...@@ -201,15 +227,13 @@ public class FlowRuleManager ...@@ -201,15 +227,13 @@ public class FlowRuleManager
201 */ 227 */
202 private static Boolean isPropertyEnabled(Dictionary<?, ?> properties, 228 private static Boolean isPropertyEnabled(Dictionary<?, ?> properties,
203 String propertyName) { 229 String propertyName) {
204 - Boolean value = null;
205 try { 230 try {
206 String s = (String) properties.get(propertyName); 231 String s = (String) properties.get(propertyName);
207 - value = isNullOrEmpty(s) ? null : s.trim().equals("true"); 232 + return isNullOrEmpty(s) ? null : s.trim().equals("true");
208 } catch (ClassCastException e) { 233 } catch (ClassCastException e) {
209 // No propertyName defined. 234 // No propertyName defined.
210 - value = null; 235 + return null;
211 } 236 }
212 - return value;
213 } 237 }
214 238
215 @Override 239 @Override
...@@ -229,8 +253,8 @@ public class FlowRuleManager ...@@ -229,8 +253,8 @@ public class FlowRuleManager
229 checkPermission(FLOWRULE_WRITE); 253 checkPermission(FLOWRULE_WRITE);
230 254
231 FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); 255 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
232 - for (int i = 0; i < flowRules.length; i++) { 256 + for (FlowRule flowRule : flowRules) {
233 - builder.add(flowRules[i]); 257 + builder.add(flowRule);
234 } 258 }
235 apply(builder.build()); 259 apply(builder.build());
236 } 260 }
...@@ -240,8 +264,8 @@ public class FlowRuleManager ...@@ -240,8 +264,8 @@ public class FlowRuleManager
240 checkPermission(FLOWRULE_WRITE); 264 checkPermission(FLOWRULE_WRITE);
241 265
242 FlowRuleOperations.Builder builder = FlowRuleOperations.builder(); 266 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
243 - for (int i = 0; i < flowRules.length; i++) { 267 + for (FlowRule flowRule : flowRules) {
244 - builder.remove(flowRules[i]); 268 + builder.remove(flowRule);
245 } 269 }
246 apply(builder.build()); 270 apply(builder.build());
247 } 271 }
...@@ -419,15 +443,9 @@ public class FlowRuleManager ...@@ -419,15 +443,9 @@ public class FlowRuleManager
419 //lastSeen.put(storedRule, currentTime); 443 //lastSeen.put(storedRule, currentTime);
420 } 444 }
421 Long last = lastSeen.get(storedRule); 445 Long last = lastSeen.get(storedRule);
422 - if (last == null) {
423 - // concurrently removed? let the liveness check fail
424 - return false;
425 - }
426 446
427 - if ((currentTime - last) <= timeout) { 447 + // concurrently removed? let the liveness check fail
428 - return true; 448 + return last != null && (currentTime - last) <= timeout;
429 - }
430 - return false;
431 } 449 }
432 450
433 @Override 451 @Override
...@@ -466,7 +484,6 @@ public class FlowRuleManager ...@@ -466,7 +484,6 @@ public class FlowRuleManager
466 } 484 }
467 } catch (Exception e) { 485 } catch (Exception e) {
468 log.debug("Can't process added or extra rule {}", e.getMessage()); 486 log.debug("Can't process added or extra rule {}", e.getMessage());
469 - continue;
470 } 487 }
471 } 488 }
472 489
...@@ -479,7 +496,6 @@ public class FlowRuleManager ...@@ -479,7 +496,6 @@ public class FlowRuleManager
479 flowMissing(rule); 496 flowMissing(rule);
480 } catch (Exception e) { 497 } catch (Exception e) {
481 log.debug("Can't add missing flow rule:", e); 498 log.debug("Can't add missing flow rule:", e);
482 - continue;
483 } 499 }
484 } 500 }
485 } 501 }
......
...@@ -21,25 +21,28 @@ import com.google.common.collect.Lists; ...@@ -21,25 +21,28 @@ import com.google.common.collect.Lists;
21 import com.google.common.collect.Sets; 21 import com.google.common.collect.Sets;
22 import com.google.common.util.concurrent.ListenableFuture; 22 import com.google.common.util.concurrent.ListenableFuture;
23 import com.google.common.util.concurrent.MoreExecutors; 23 import com.google.common.util.concurrent.MoreExecutors;
24 -
25 import org.junit.After; 24 import org.junit.After;
26 import org.junit.Before; 25 import org.junit.Before;
27 import org.junit.Test; 26 import org.junit.Test;
27 +import org.onlab.junit.TestTools;
28 import org.onosproject.cfg.ComponentConfigAdapter; 28 import org.onosproject.cfg.ComponentConfigAdapter;
29 +import org.onosproject.common.event.impl.TestEventDispatcher;
29 import org.onosproject.core.ApplicationId; 30 import org.onosproject.core.ApplicationId;
30 import org.onosproject.core.CoreServiceAdapter; 31 import org.onosproject.core.CoreServiceAdapter;
31 import org.onosproject.core.DefaultApplicationId; 32 import org.onosproject.core.DefaultApplicationId;
32 import org.onosproject.core.IdGenerator; 33 import org.onosproject.core.IdGenerator;
33 -import org.onosproject.common.event.impl.TestEventDispatcher; 34 +import org.onosproject.mastership.MastershipServiceAdapter;
35 +import org.onosproject.net.AnnotationKeys;
36 +import org.onosproject.net.DefaultAnnotations;
34 import org.onosproject.net.DefaultDevice; 37 import org.onosproject.net.DefaultDevice;
35 import org.onosproject.net.Device; 38 import org.onosproject.net.Device;
36 import org.onosproject.net.Device.Type; 39 import org.onosproject.net.Device.Type;
37 import org.onosproject.net.DeviceId; 40 import org.onosproject.net.DeviceId;
38 import org.onosproject.net.MastershipRole; 41 import org.onosproject.net.MastershipRole;
39 -import org.onosproject.net.Port;
40 -import org.onosproject.net.PortNumber;
41 -import org.onosproject.net.device.DeviceListener;
42 import org.onosproject.net.device.DeviceServiceAdapter; 42 import org.onosproject.net.device.DeviceServiceAdapter;
43 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
44 +import org.onosproject.net.driver.DefaultDriver;
45 +import org.onosproject.net.driver.impl.DriverManager;
43 import org.onosproject.net.flow.CompletedBatchOperation; 46 import org.onosproject.net.flow.CompletedBatchOperation;
44 import org.onosproject.net.flow.DefaultFlowEntry; 47 import org.onosproject.net.flow.DefaultFlowEntry;
45 import org.onosproject.net.flow.DefaultFlowRule; 48 import org.onosproject.net.flow.DefaultFlowRule;
...@@ -49,6 +52,7 @@ import org.onosproject.net.flow.FlowRule; ...@@ -49,6 +52,7 @@ import org.onosproject.net.flow.FlowRule;
49 import org.onosproject.net.flow.FlowRuleBatchOperation; 52 import org.onosproject.net.flow.FlowRuleBatchOperation;
50 import org.onosproject.net.flow.FlowRuleEvent; 53 import org.onosproject.net.flow.FlowRuleEvent;
51 import org.onosproject.net.flow.FlowRuleListener; 54 import org.onosproject.net.flow.FlowRuleListener;
55 +import org.onosproject.net.flow.FlowRuleProgrammable;
52 import org.onosproject.net.flow.FlowRuleProvider; 56 import org.onosproject.net.flow.FlowRuleProvider;
53 import org.onosproject.net.flow.FlowRuleProviderRegistry; 57 import org.onosproject.net.flow.FlowRuleProviderRegistry;
54 import org.onosproject.net.flow.FlowRuleProviderService; 58 import org.onosproject.net.flow.FlowRuleProviderService;
...@@ -65,8 +69,10 @@ import org.onosproject.net.provider.ProviderId; ...@@ -65,8 +69,10 @@ import org.onosproject.net.provider.ProviderId;
65 import org.onosproject.store.trivial.SimpleFlowRuleStore; 69 import org.onosproject.store.trivial.SimpleFlowRuleStore;
66 70
67 import java.util.ArrayList; 71 import java.util.ArrayList;
72 +import java.util.Collection;
68 import java.util.Collections; 73 import java.util.Collections;
69 import java.util.HashMap; 74 import java.util.HashMap;
75 +import java.util.HashSet;
70 import java.util.List; 76 import java.util.List;
71 import java.util.Map; 77 import java.util.Map;
72 import java.util.Set; 78 import java.util.Set;
...@@ -76,16 +82,9 @@ import java.util.concurrent.TimeUnit; ...@@ -76,16 +82,9 @@ import java.util.concurrent.TimeUnit;
76 import java.util.concurrent.TimeoutException; 82 import java.util.concurrent.TimeoutException;
77 import java.util.concurrent.atomic.AtomicLong; 83 import java.util.concurrent.atomic.AtomicLong;
78 84
79 -import static org.junit.Assert.assertEquals; 85 +import static org.junit.Assert.*;
80 -import static org.junit.Assert.assertFalse;
81 -import static org.junit.Assert.assertNotNull;
82 -import static org.junit.Assert.assertTrue;
83 import static org.onosproject.net.NetTestTools.injectEventDispatcher; 86 import static org.onosproject.net.NetTestTools.injectEventDispatcher;
84 -import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_ADDED; 87 +import static org.onosproject.net.flow.FlowRuleEvent.Type.*;
85 -import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_ADD_REQUESTED;
86 -import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
87 -import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_REMOVE_REQUESTED;
88 -import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
89 88
90 /** 89 /**
91 * Test codifying the flow rule service & flow rule provider service contracts. 90 * Test codifying the flow rule service & flow rule provider service contracts.
...@@ -94,10 +93,19 @@ public class FlowRuleManagerTest { ...@@ -94,10 +93,19 @@ public class FlowRuleManagerTest {
94 93
95 94
96 private static final ProviderId PID = new ProviderId("of", "foo"); 95 private static final ProviderId PID = new ProviderId("of", "foo");
96 + private static final ProviderId FOO_PID = new ProviderId("foo", "foo");
97 +
97 private static final DeviceId DID = DeviceId.deviceId("of:001"); 98 private static final DeviceId DID = DeviceId.deviceId("of:001");
99 + private static final DeviceId FOO_DID = DeviceId.deviceId("foo:002");
98 private static final int TIMEOUT = 10; 100 private static final int TIMEOUT = 10;
99 - private static final Device DEV = new DefaultDevice( 101 +
100 - PID, DID, Type.SWITCH, "", "", "", "", null); 102 + private static final DefaultAnnotations ANNOTATIONS =
103 + DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, "foo").build();
104 +
105 + private static final Device DEV =
106 + new DefaultDevice(PID, DID, Type.SWITCH, "", "", "", "", null);
107 + private static final Device FOO_DEV =
108 + new DefaultDevice(FOO_PID, FOO_DID, Type.SWITCH, "", "", "", "", null, ANNOTATIONS);
101 109
102 private FlowRuleManager mgr; 110 private FlowRuleManager mgr;
103 111
...@@ -108,6 +116,8 @@ public class FlowRuleManagerTest { ...@@ -108,6 +116,8 @@ public class FlowRuleManagerTest {
108 protected TestListener listener = new TestListener(); 116 protected TestListener listener = new TestListener();
109 private ApplicationId appId; 117 private ApplicationId appId;
110 118
119 + private TestDriverManager driverService;
120 +
111 121
112 @Before 122 @Before
113 public void setUp() { 123 public void setUp() {
...@@ -115,6 +125,7 @@ public class FlowRuleManagerTest { ...@@ -115,6 +125,7 @@ public class FlowRuleManagerTest {
115 mgr.store = new SimpleFlowRuleStore(); 125 mgr.store = new SimpleFlowRuleStore();
116 injectEventDispatcher(mgr, new TestEventDispatcher()); 126 injectEventDispatcher(mgr, new TestEventDispatcher());
117 mgr.deviceService = new TestDeviceService(); 127 mgr.deviceService = new TestDeviceService();
128 + mgr.mastershipService = new TestMastershipService();
118 mgr.coreService = new TestCoreService(); 129 mgr.coreService = new TestCoreService();
119 mgr.operationsService = MoreExecutors.newDirectExecutorService(); 130 mgr.operationsService = MoreExecutors.newDirectExecutorService();
120 mgr.deviceInstallers = MoreExecutors.newDirectExecutorService(); 131 mgr.deviceInstallers = MoreExecutors.newDirectExecutorService();
...@@ -122,6 +133,12 @@ public class FlowRuleManagerTest { ...@@ -122,6 +133,12 @@ public class FlowRuleManagerTest {
122 service = mgr; 133 service = mgr;
123 registry = mgr; 134 registry = mgr;
124 135
136 + driverService = new TestDriverManager();
137 + driverService.addDriver(new DefaultDriver("foo", ImmutableList.of(), "", "", "",
138 + ImmutableMap.of(FlowRuleProgrammable.class,
139 + TestFlowRuleProgrammable.class),
140 + ImmutableMap.of()));
141 +
125 mgr.activate(null); 142 mgr.activate(null);
126 mgr.addListener(listener); 143 mgr.addListener(listener);
127 provider = new TestProvider(PID); 144 provider = new TestProvider(PID);
...@@ -143,10 +160,14 @@ public class FlowRuleManagerTest { ...@@ -143,10 +160,14 @@ public class FlowRuleManagerTest {
143 } 160 }
144 161
145 private FlowRule flowRule(int tsval, int trval) { 162 private FlowRule flowRule(int tsval, int trval) {
163 + return flowRule(DID, tsval, trval);
164 + }
165 +
166 + private FlowRule flowRule(DeviceId did, int tsval, int trval) {
146 TestSelector ts = new TestSelector(tsval); 167 TestSelector ts = new TestSelector(tsval);
147 TestTreatment tr = new TestTreatment(trval); 168 TestTreatment tr = new TestTreatment(trval);
148 return DefaultFlowRule.builder() 169 return DefaultFlowRule.builder()
149 - .forDevice(DID) 170 + .forDevice(did)
150 .withSelector(ts) 171 .withSelector(ts)
151 .withTreatment(tr) 172 .withTreatment(tr)
152 .withPriority(10) 173 .withPriority(10)
...@@ -155,7 +176,6 @@ public class FlowRuleManagerTest { ...@@ -155,7 +176,6 @@ public class FlowRuleManagerTest {
155 .build(); 176 .build();
156 } 177 }
157 178
158 -
159 private FlowRule addFlowRule(int hval) { 179 private FlowRule addFlowRule(int hval) {
160 FlowRule rule = flowRule(hval, hval); 180 FlowRule rule = flowRule(hval, hval);
161 service.applyFlowRules(rule); 181 service.applyFlowRules(rule);
...@@ -398,60 +418,80 @@ public class FlowRuleManagerTest { ...@@ -398,60 +418,80 @@ public class FlowRuleManagerTest {
398 f2, FlowEntryState.PENDING_REMOVE)); 418 f2, FlowEntryState.PENDING_REMOVE));
399 } 419 }
400 420
401 - private static class TestListener implements FlowRuleListener { 421 + @Test
402 - final List<FlowRuleEvent> events = new ArrayList<>(); 422 + public void fallbackBasics() {
423 + FlowRule f1 = flowRule(FOO_DID, 1, 1);
424 + flowRules.clear();
425 + mgr.applyFlowRules(f1);
426 + assertTrue("flow rule not applied", flowRules.contains(f1));
403 427
404 - @Override 428 + flowRules.clear();
405 - public void event(FlowRuleEvent event) { 429 + mgr.removeFlowRules(f1);
406 - events.add(event); 430 + assertTrue("flow rule not removed", flowRules.contains(f1));
407 - }
408 } 431 }
409 432
410 - private static class TestDeviceService extends DeviceServiceAdapter { 433 + @Test
411 - 434 + public void fallbackFlowRemoved() {
412 - @Override 435 + FlowRule f1 = flowRule(FOO_DID, 1, 1);
413 - public int getDeviceCount() { 436 + mgr.applyFlowRules(f1);
414 - return 1; 437 + flowRules.clear();
438 + providerService.flowRemoved(new DefaultFlowEntry(f1));
439 + assertTrue("flow rule not reapplied", flowRules.contains(f1));
415 } 440 }
416 441
417 - @Override 442 + @Test
418 - public Iterable<Device> getDevices() { 443 + public void fallbackExtraFlow() {
419 - return Collections.singletonList(DEV); 444 + FlowRule f1 = flowRule(FOO_DID, 1, 1);
445 + flowRules.clear();
446 + providerService.pushFlowMetrics(FOO_DID, ImmutableList.of(new DefaultFlowEntry(f1)));
447 + assertTrue("flow rule not removed", flowRules.contains(f1));
420 } 448 }
421 449
422 - @Override 450 + @Test
423 - public Device getDevice(DeviceId deviceId) { 451 + public void fallbackPoll() {
424 - return DEV; 452 + FlowRuleDriverProvider fallback = (FlowRuleDriverProvider) mgr.defaultProvider();
425 - } 453 + FlowRule f1 = flowRule(FOO_DID, 1, 1);
454 + mgr.applyFlowRules(f1);
455 + FlowEntry fe = mgr.getFlowEntries(FOO_DID).iterator().next();
456 + assertEquals("incorrect state", FlowEntryState.PENDING_ADD, fe.state());
426 457
427 - @Override 458 + fallback.init(fallback.providerService, mgr.deviceService, mgr.mastershipService, 1);
428 - public MastershipRole getRole(DeviceId deviceId) { 459 + TestTools.assertAfter(2000, () -> {
429 - return null; 460 + FlowEntry e = mgr.getFlowEntries(FOO_DID).iterator().next();
461 + assertEquals("incorrect state", FlowEntryState.ADDED, e.state());
462 + });
430 } 463 }
431 464
465 +
466 + private static class TestListener implements FlowRuleListener {
467 + final List<FlowRuleEvent> events = new ArrayList<>();
468 +
432 @Override 469 @Override
433 - public List<Port> getPorts(DeviceId deviceId) { 470 + public void event(FlowRuleEvent event) {
434 - return null; 471 + events.add(event);
472 + }
435 } 473 }
436 474
475 + private static class TestDeviceService extends DeviceServiceAdapter {
437 @Override 476 @Override
438 - public Port getPort(DeviceId deviceId, PortNumber portNumber) { 477 + public int getDeviceCount() {
439 - return null; 478 + return 2;
440 } 479 }
441 480
442 @Override 481 @Override
443 - public boolean isAvailable(DeviceId deviceId) { 482 + public Iterable<Device> getDevices() {
444 - return false; 483 + return ImmutableList.of(DEV, FOO_DEV);
445 } 484 }
446 485
447 @Override 486 @Override
448 - public void addListener(DeviceListener listener) { 487 + public Iterable<Device> getAvailableDevices() {
488 + return getDevices();
449 } 489 }
450 490
451 @Override 491 @Override
452 - public void removeListener(DeviceListener listener) { 492 + public Device getDevice(DeviceId deviceId) {
493 + return deviceId.equals(FOO_DID) ? FOO_DEV : DEV;
453 } 494 }
454 -
455 } 495 }
456 496
457 private class TestProvider extends AbstractProvider implements FlowRuleProvider { 497 private class TestProvider extends AbstractProvider implements FlowRuleProvider {
...@@ -624,6 +664,7 @@ public class FlowRuleManagerTest { ...@@ -624,6 +664,7 @@ public class FlowRuleManagerTest {
624 public IdGenerator getIdGenerator(String topic) { 664 public IdGenerator getIdGenerator(String topic) {
625 return new IdGenerator() { 665 return new IdGenerator() {
626 private AtomicLong counter = new AtomicLong(0); 666 private AtomicLong counter = new AtomicLong(0);
667 +
627 @Override 668 @Override
628 public long getNewId() { 669 public long getNewId() {
629 return counter.getAndIncrement(); 670 return counter.getAndIncrement();
...@@ -632,4 +673,41 @@ public class FlowRuleManagerTest { ...@@ -632,4 +673,41 @@ public class FlowRuleManagerTest {
632 } 673 }
633 } 674 }
634 675
676 + private class TestMastershipService extends MastershipServiceAdapter {
677 + @Override
678 + public MastershipRole getLocalRole(DeviceId deviceId) {
679 + return MastershipRole.MASTER;
680 + }
681 + }
682 +
683 + private class TestDriverManager extends DriverManager {
684 + TestDriverManager() {
685 + this.deviceService = mgr.deviceService;
686 + activate();
687 + }
688 + }
689 +
690 + static Collection<FlowRule> flowRules = new HashSet<>();
691 +
692 + public static class TestFlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
693 +
694 + @Override
695 + public Collection<FlowEntry> getFlowEntries() {
696 + ImmutableList.Builder<FlowEntry> builder = ImmutableList.builder();
697 + flowRules.stream().map(DefaultFlowEntry::new).forEach(builder::add);
698 + return builder.build();
699 + }
700 +
701 + @Override
702 + public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
703 + flowRules.addAll(rules);
704 + return rules;
705 + }
706 +
707 + @Override
708 + public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
709 + flowRules.addAll(rules);
710 + return rules;
711 + }
712 + }
635 } 713 }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
9 aux=/tmp/stc-$$.log 9 aux=/tmp/stc-$$.log
10 trap "rm -f $aux $aux.1 $aux.2 2>/dev/null" EXIT 10 trap "rm -f $aux $aux.1 $aux.2 2>/dev/null" EXIT
11 11
12 -for attempt in {1..3}; do 12 +for attempt in {1..10}; do
13 onos ${1:-$OCI} "onos:apps -s -a" | grep -v /bin/client > $aux 13 onos ${1:-$OCI} "onos:apps -s -a" | grep -v /bin/client > $aux
14 cat $aux 14 cat $aux
15 15
......