alshabib

WIP: Initial implementation of filterObjectives using driver subsystem.

Incomplete implementation

Change-Id: I3745d481027659d4ca44b72139e5461c02e8c3ef
...@@ -26,4 +26,9 @@ public class AbstractBehaviour implements Behaviour { ...@@ -26,4 +26,9 @@ public class AbstractBehaviour implements Behaviour {
26 public void setData(DriverData data) { 26 public void setData(DriverData data) {
27 this.data = data; 27 this.data = data;
28 } 28 }
29 +
30 + @Override
31 + public DriverData data() {
32 + return data;
33 + }
29 } 34 }
......
...@@ -29,4 +29,11 @@ public interface Behaviour { ...@@ -29,4 +29,11 @@ public interface Behaviour {
29 */ 29 */
30 void setData(DriverData data); 30 void setData(DriverData data);
31 31
32 + /**
33 + * Obtains the driver data.
34 + *
35 + * @return driver data
36 + */
37 + DriverData data();
38 +
32 } 39 }
......
...@@ -32,7 +32,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -32,7 +32,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
32 public final class DefaultFilteringObjective implements FilteringObjective { 32 public final class DefaultFilteringObjective implements FilteringObjective {
33 33
34 34
35 - private final Criterion key; 35 + private final Type type;
36 private final boolean permanent; 36 private final boolean permanent;
37 private final int timeout; 37 private final int timeout;
38 private final ApplicationId appId; 38 private final ApplicationId appId;
...@@ -41,10 +41,10 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -41,10 +41,10 @@ public final class DefaultFilteringObjective implements FilteringObjective {
41 private final int id; 41 private final int id;
42 private final Operation op; 42 private final Operation op;
43 43
44 - private DefaultFilteringObjective(Criterion key, boolean permanent, int timeout, 44 + private DefaultFilteringObjective(Type type, boolean permanent, int timeout,
45 ApplicationId appId, int priority, 45 ApplicationId appId, int priority,
46 List<Criterion> conditions, Operation op) { 46 List<Criterion> conditions, Operation op) {
47 - this.key = key; 47 + this.type = type;
48 this.permanent = permanent; 48 this.permanent = permanent;
49 this.timeout = timeout; 49 this.timeout = timeout;
50 this.appId = appId; 50 this.appId = appId;
...@@ -52,14 +52,13 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -52,14 +52,13 @@ public final class DefaultFilteringObjective implements FilteringObjective {
52 this.conditions = conditions; 52 this.conditions = conditions;
53 this.op = op; 53 this.op = op;
54 54
55 - this.id = Objects.hash(key, conditions, permanent, 55 + this.id = Objects.hash(type, conditions, permanent,
56 timeout, appId, priority); 56 timeout, appId, priority);
57 } 57 }
58 58
59 -
60 @Override 59 @Override
61 - public Criterion key() { 60 + public Type type() {
62 - return key; 61 + return this.type;
63 } 62 }
64 63
65 @Override 64 @Override
...@@ -111,7 +110,7 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -111,7 +110,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
111 private final ImmutableList.Builder<Criterion> listBuilder 110 private final ImmutableList.Builder<Criterion> listBuilder
112 = ImmutableList.builder(); 111 = ImmutableList.builder();
113 112
114 - private Criterion key; 113 + private Type type;
115 private boolean permanent = DEFAULT_PERMANENT; 114 private boolean permanent = DEFAULT_PERMANENT;
116 private int timeout = DEFAULT_TIMEOUT; 115 private int timeout = DEFAULT_TIMEOUT;
117 private ApplicationId appId; 116 private ApplicationId appId;
...@@ -124,8 +123,14 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -124,8 +123,14 @@ public final class DefaultFilteringObjective implements FilteringObjective {
124 } 123 }
125 124
126 @Override 125 @Override
127 - public Builder withKey(Criterion criterion) { 126 + public Builder permit() {
128 - key = criterion; 127 + this.type = Type.PERMIT;
128 + return this;
129 + }
130 +
131 + @Override
132 + public Builder deny() {
133 + this.type = Type.DENY;
129 return this; 134 return this;
130 } 135 }
131 136
...@@ -157,11 +162,11 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -157,11 +162,11 @@ public final class DefaultFilteringObjective implements FilteringObjective {
157 @Override 162 @Override
158 public FilteringObjective add() { 163 public FilteringObjective add() {
159 List<Criterion> conditions = listBuilder.build(); 164 List<Criterion> conditions = listBuilder.build();
160 - checkNotNull(key, "Must have a key."); 165 + checkNotNull(type, "Must have a type.");
161 checkArgument(!conditions.isEmpty(), "Must have at least one condition."); 166 checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
162 checkNotNull(appId, "Must supply an application id"); 167 checkNotNull(appId, "Must supply an application id");
163 168
164 - return new DefaultFilteringObjective(key, permanent, timeout, 169 + return new DefaultFilteringObjective(type, permanent, timeout,
165 appId, priority, conditions, 170 appId, priority, conditions,
166 Operation.ADD); 171 Operation.ADD);
167 172
...@@ -170,11 +175,11 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -170,11 +175,11 @@ public final class DefaultFilteringObjective implements FilteringObjective {
170 @Override 175 @Override
171 public FilteringObjective remove() { 176 public FilteringObjective remove() {
172 List<Criterion> conditions = listBuilder.build(); 177 List<Criterion> conditions = listBuilder.build();
173 - checkNotNull(key, "Must have a key."); 178 + checkNotNull(type, "Must have a type.");
174 checkArgument(!conditions.isEmpty(), "Must have at least one condition."); 179 checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
175 checkNotNull(appId, "Must supply an application id"); 180 checkNotNull(appId, "Must supply an application id");
176 181
177 - return new DefaultFilteringObjective(key, permanent, timeout, 182 + return new DefaultFilteringObjective(type, permanent, timeout,
178 appId, priority, conditions, 183 appId, priority, conditions,
179 Operation.REMOVE); 184 Operation.REMOVE);
180 185
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.net.flowobjective; 16 package org.onosproject.net.flowobjective;
17 17
18 +import org.onosproject.core.ApplicationId;
18 import org.onosproject.net.flow.criteria.Criterion; 19 import org.onosproject.net.flow.criteria.Criterion;
19 20
20 import java.util.Collection; 21 import java.util.Collection;
...@@ -27,12 +28,23 @@ import java.util.Collection; ...@@ -27,12 +28,23 @@ import java.util.Collection;
27 */ 28 */
28 public interface FilteringObjective extends Objective { 29 public interface FilteringObjective extends Objective {
29 30
31 + enum Type {
32 + /**
33 + * Enables the filtering condition.
34 + */
35 + PERMIT,
36 +
37 + /**
38 + * Disables the filtering condition.
39 + */
40 + DENY
41 + }
42 +
30 /** 43 /**
31 - * Represents filtering key used in this filter. 44 + * Obtain this filtering type.
32 - * 45 + * @return the type
33 - * @return a criterion
34 */ 46 */
35 - Criterion key(); 47 + public Type type();
36 48
37 /** 49 /**
38 * The set of conditions the filter must provision at the device. 50 * The set of conditions the filter must provision at the device.
...@@ -55,12 +67,23 @@ public interface FilteringObjective extends Objective { ...@@ -55,12 +67,23 @@ public interface FilteringObjective extends Objective {
55 public Builder addCondition(Criterion criterion); 67 public Builder addCondition(Criterion criterion);
56 68
57 /** 69 /**
58 - * Add a filtering key. 70 + * Permit this filtering condition set.
59 - * 71 + * @return a filtering builder
60 - * @param criterion new criterion 72 + */
61 - * @return a filtering builder. 73 + public Builder permit();
74 +
75 + /**
76 + * Deny this filtering condition set.
77 + * @return a filtering builder
78 + */
79 + public Builder deny();
80 +
81 + /**
82 + * Assigns an application id.
83 + * @param appId an application id
84 + * @return a filtering builder
62 */ 85 */
63 - public Builder withKey(Criterion criterion); 86 + public Builder fromApp(ApplicationId appId);
64 87
65 /** 88 /**
66 * Builds the filtering objective that will be added. 89 * Builds the filtering objective that will be added.
......
...@@ -15,7 +15,9 @@ ...@@ -15,7 +15,9 @@
15 */ 15 */
16 package org.onosproject.net.flowobjective.impl; 16 package org.onosproject.net.flowobjective.impl;
17 17
18 +import com.google.common.collect.Lists;
18 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
20 +import com.google.common.util.concurrent.Futures;
19 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
20 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
21 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -43,11 +45,13 @@ import org.onosproject.net.flowobjective.FilteringObjective; ...@@ -43,11 +45,13 @@ import org.onosproject.net.flowobjective.FilteringObjective;
43 import org.onosproject.net.flowobjective.FlowObjectiveService; 45 import org.onosproject.net.flowobjective.FlowObjectiveService;
44 import org.onosproject.net.flowobjective.ForwardingObjective; 46 import org.onosproject.net.flowobjective.ForwardingObjective;
45 import org.onosproject.net.flowobjective.NextObjective; 47 import org.onosproject.net.flowobjective.NextObjective;
48 +import org.onosproject.net.flowobjective.Objective;
46 import org.onosproject.net.group.GroupService; 49 import org.onosproject.net.group.GroupService;
47 import org.slf4j.Logger; 50 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory; 51 import org.slf4j.LoggerFactory;
49 52
50 import java.util.Collection; 53 import java.util.Collection;
54 +import java.util.Collections;
51 import java.util.Map; 55 import java.util.Map;
52 import java.util.concurrent.Future; 56 import java.util.concurrent.Future;
53 57
...@@ -87,12 +91,16 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -87,12 +91,16 @@ public class FlowObjectiveManager implements FlowObjectiveService {
87 91
88 92
89 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap(); 93 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
94 + private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap();
90 95
91 private final PipelinerContext context = new InnerPipelineContext(); 96 private final PipelinerContext context = new InnerPipelineContext();
92 private final MastershipListener mastershipListener = new InnerMastershipListener(); 97 private final MastershipListener mastershipListener = new InnerMastershipListener();
93 private final DeviceListener deviceListener = new InnerDeviceListener(); 98 private final DeviceListener deviceListener = new InnerDeviceListener();
94 99
95 protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); 100 protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
101 +
102 + private final Map<DeviceId, Collection<Objective>> pendingObjectives =
103 + Maps.newConcurrentMap();
96 private NodeId localNode; 104 private NodeId localNode;
97 105
98 @Activate 106 @Activate
...@@ -114,26 +122,51 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -114,26 +122,51 @@ public class FlowObjectiveManager implements FlowObjectiveService {
114 @Override 122 @Override
115 public Future<Boolean> filter(DeviceId deviceId, 123 public Future<Boolean> filter(DeviceId deviceId,
116 Collection<FilteringObjective> filteringObjectives) { 124 Collection<FilteringObjective> filteringObjectives) {
117 - return getDevicePipeliner(deviceId).filter(filteringObjectives); 125 + if (deviceService.isAvailable(deviceId)) {
126 + return getDevicePipeliner(deviceId).filter(filteringObjectives);
127 + } else {
128 + filteringObjectives.forEach(obj -> updatePendingMap(deviceId, obj));
129 + }
130 + return Futures.immediateFuture(true);
118 } 131 }
119 132
133 +
134 +
120 @Override 135 @Override
121 public Future<Boolean> forward(DeviceId deviceId, 136 public Future<Boolean> forward(DeviceId deviceId,
122 Collection<ForwardingObjective> forwardingObjectives) { 137 Collection<ForwardingObjective> forwardingObjectives) {
123 - return getDevicePipeliner(deviceId).forward(forwardingObjectives); 138 + if (deviceService.isAvailable(deviceId)) {
139 + return getDevicePipeliner(deviceId).forward(forwardingObjectives);
140 + } else {
141 + forwardingObjectives.forEach(obj -> updatePendingMap(deviceId, obj));
142 + }
143 + return Futures.immediateFuture(true);
124 } 144 }
125 145
126 @Override 146 @Override
127 public Future<Boolean> next(DeviceId deviceId, 147 public Future<Boolean> next(DeviceId deviceId,
128 Collection<NextObjective> nextObjectives) { 148 Collection<NextObjective> nextObjectives) {
129 - return getDevicePipeliner(deviceId).next(nextObjectives); 149 + if (deviceService.isAvailable(deviceId)) {
150 + return getDevicePipeliner(deviceId).next(nextObjectives);
151 + } else {
152 + nextObjectives.forEach(obj -> updatePendingMap(deviceId, obj));
153 + }
154 + return Futures.immediateFuture(true);
130 } 155 }
131 156
132 - // Retrieves the device handler pipeline behaviour from the cache. 157 + private void updatePendingMap(DeviceId deviceId, Objective pending) {
158 + if (pendingObjectives.putIfAbsent(deviceId, Lists.newArrayList(pending)) != null) {
159 + Collection<Objective> objectives = pendingObjectives.get(deviceId);
160 + objectives.add(pending);
161 + }
162 +
163 + }
164 +
165 + // Retrieves the device pipeline behaviour from the cache.
133 private Pipeliner getDevicePipeliner(DeviceId deviceId) { 166 private Pipeliner getDevicePipeliner(DeviceId deviceId) {
134 - DriverHandler handler = driverHandlers.get(deviceId); 167 + Pipeliner pipeliner = pipeliners.get(deviceId);
135 - checkState(handler != null, NOT_INITIALIZED); 168 + checkState(pipeliner != null, NOT_INITIALIZED);
136 - return handler != null ? handler.behaviour(Pipeliner.class) : null; 169 + return pipeliner;
137 } 170 }
138 171
139 172
...@@ -164,6 +197,7 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -164,6 +197,7 @@ public class FlowObjectiveManager implements FlowObjectiveService {
164 case DEVICE_AVAILABILITY_CHANGED: 197 case DEVICE_AVAILABILITY_CHANGED:
165 if (deviceService.isAvailable(event.subject().id())) { 198 if (deviceService.isAvailable(event.subject().id())) {
166 setupPipelineHandler(event.subject().id()); 199 setupPipelineHandler(event.subject().id());
200 + processPendingObjectives(event.subject().id());
167 } 201 }
168 break; 202 break;
169 case DEVICE_UPDATED: 203 case DEVICE_UPDATED:
...@@ -182,6 +216,21 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -182,6 +216,21 @@ public class FlowObjectiveManager implements FlowObjectiveService {
182 break; 216 break;
183 } 217 }
184 } 218 }
219 +
220 + private void processPendingObjectives(DeviceId deviceId) {
221 + pendingObjectives.get(deviceId).forEach(obj -> {
222 + if (obj instanceof NextObjective) {
223 + getDevicePipeliner(deviceId)
224 + .next(Collections.singletonList((NextObjective) obj));
225 + } else if (obj instanceof ForwardingObjective) {
226 + getDevicePipeliner(deviceId)
227 + .forward(Collections.singletonList((ForwardingObjective) obj));
228 + } else {
229 + getDevicePipeliner(deviceId)
230 + .filter(Collections.singletonList((FilteringObjective) obj));
231 + }
232 + });
233 + }
185 } 234 }
186 235
187 private void setupPipelineHandler(DeviceId deviceId) { 236 private void setupPipelineHandler(DeviceId deviceId) {
...@@ -205,7 +254,9 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -205,7 +254,9 @@ public class FlowObjectiveManager implements FlowObjectiveService {
205 } 254 }
206 255
207 // Always (re)initialize the pipeline behaviour 256 // Always (re)initialize the pipeline behaviour
208 - handler.behaviour(Pipeliner.class).init(deviceId, context); 257 + Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
258 + pipeliner.init(deviceId, context);
259 + pipeliners.putIfAbsent(deviceId, pipeliner);
209 log.info("Driver {} bound to device {}", handler.driver().name(), deviceId); 260 log.info("Driver {} bound to device {}", handler.driver().name(), deviceId);
210 } 261 }
211 } 262 }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onosproject.driver.pipeline; 16 package org.onosproject.driver.pipeline;
17 17
18 +import com.google.common.collect.Sets;
19 +import com.google.common.util.concurrent.SettableFuture;
18 import org.onlab.osgi.ServiceDirectory; 20 import org.onlab.osgi.ServiceDirectory;
19 import org.onlab.packet.Ethernet; 21 import org.onlab.packet.Ethernet;
20 import org.onlab.packet.MacAddress; 22 import org.onlab.packet.MacAddress;
...@@ -34,9 +36,12 @@ import org.onosproject.net.flow.FlowRuleOperationsContext; ...@@ -34,9 +36,12 @@ import org.onosproject.net.flow.FlowRuleOperationsContext;
34 import org.onosproject.net.flow.FlowRuleService; 36 import org.onosproject.net.flow.FlowRuleService;
35 import org.onosproject.net.flow.TrafficSelector; 37 import org.onosproject.net.flow.TrafficSelector;
36 import org.onosproject.net.flow.TrafficTreatment; 38 import org.onosproject.net.flow.TrafficTreatment;
39 +import org.onosproject.net.flow.criteria.Criteria;
40 +import org.onosproject.net.flow.criteria.Criterion;
37 import org.onosproject.net.flowobjective.FilteringObjective; 41 import org.onosproject.net.flowobjective.FilteringObjective;
38 import org.onosproject.net.flowobjective.ForwardingObjective; 42 import org.onosproject.net.flowobjective.ForwardingObjective;
39 import org.onosproject.net.flowobjective.NextObjective; 43 import org.onosproject.net.flowobjective.NextObjective;
44 +import org.onosproject.net.flowobjective.Objective;
40 import org.slf4j.Logger; 45 import org.slf4j.Logger;
41 46
42 import java.util.Collection; 47 import java.util.Collection;
...@@ -79,7 +84,54 @@ public class OVSCorsaPipeline extends AbstractBehaviour implements Pipeliner { ...@@ -79,7 +84,54 @@ public class OVSCorsaPipeline extends AbstractBehaviour implements Pipeliner {
79 84
80 @Override 85 @Override
81 public Future<Boolean> filter(Collection<FilteringObjective> filteringObjectives) { 86 public Future<Boolean> filter(Collection<FilteringObjective> filteringObjectives) {
82 - return null; 87 + Collection<Future<Boolean>> results =
88 + Sets.newHashSet();
89 + filteringObjectives.stream()
90 + .filter(obj -> obj.type() == FilteringObjective.Type.PERMIT)
91 + .forEach(obj -> obj.conditions()
92 + .forEach(condition ->
93 + results.add(processCondition(condition,
94 + obj.op() == Objective.Operation.ADD,
95 + obj.appId()))
96 + ));
97 +
98 + //TODO: return something more helpful/sensible in the future (no pun intended)
99 + return results.iterator().next();
100 +
101 + }
102 +
103 + private Future<Boolean> processCondition(Criterion c, boolean install,
104 + ApplicationId applicationId) {
105 + SettableFuture<Boolean> result = SettableFuture.create();
106 + if (c.type() == Criterion.Type.ETH_DST) {
107 + Criteria.EthCriterion e = (Criteria.EthCriterion) c;
108 + log.debug("adding rule for MAC: {}", e.mac());
109 +
110 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
111 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
112 + selector.matchEthDst(e.mac());
113 + treatment.transition(FlowRule.Type.VLAN_MPLS);
114 + FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
115 + treatment.build(),
116 + CONTROLLER_PRIORITY, applicationId, 0,
117 + true, FlowRule.Type.FIRST);
118 + FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
119 + ops = install ? ops.add(rule) : ops.remove(rule);
120 + flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
121 + @Override
122 + public void onSuccess(FlowRuleOperations ops) {
123 + result.set(true);
124 + log.info("Provisioned default table for bgp router");
125 + }
126 +
127 + @Override
128 + public void onError(FlowRuleOperations ops) {
129 + result.set(false);
130 + log.info("Failed to provision default table for bgp router");
131 + }
132 + }));
133 + }
134 + return result;
83 } 135 }
84 136
85 @Override 137 @Override
......