alshabib
Committed by Gerrit Code Review

Flow Objective implementation

Provides an abstraction which isolates the application from any pipeline
knowledge. By using the provided objectives applications can express
their forwarding desires in a pipeline agnostic way. The objectives
are then consumed by a driver for the specific device who converts them
into the appropriate pipeline coherent flows.

Change-Id: I74a68b4971c367c0cd5b7de9d877abdd117afa98
Showing 26 changed files with 1133 additions and 211 deletions
...@@ -20,7 +20,6 @@ import com.google.common.collect.HashMultimap; ...@@ -20,7 +20,6 @@ import com.google.common.collect.HashMultimap;
20 import com.google.common.collect.Maps; 20 import com.google.common.collect.Maps;
21 import com.google.common.collect.Multimap; 21 import com.google.common.collect.Multimap;
22 import com.google.common.collect.Multiset; 22 import com.google.common.collect.Multiset;
23 -
24 import org.apache.felix.scr.annotations.Activate; 23 import org.apache.felix.scr.annotations.Activate;
25 import org.apache.felix.scr.annotations.Component; 24 import org.apache.felix.scr.annotations.Component;
26 import org.apache.felix.scr.annotations.Deactivate; 25 import org.apache.felix.scr.annotations.Deactivate;
...@@ -28,35 +27,29 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -28,35 +27,29 @@ import org.apache.felix.scr.annotations.Reference;
28 import org.apache.felix.scr.annotations.ReferenceCardinality; 27 import org.apache.felix.scr.annotations.ReferenceCardinality;
29 import org.onlab.packet.Ethernet; 28 import org.onlab.packet.Ethernet;
30 import org.onlab.packet.Ip4Address; 29 import org.onlab.packet.Ip4Address;
30 +import org.onlab.packet.Ip4Prefix;
31 import org.onlab.packet.Ip6Address; 31 import org.onlab.packet.Ip6Address;
32 import org.onlab.packet.IpAddress; 32 import org.onlab.packet.IpAddress;
33 import org.onlab.packet.IpPrefix; 33 import org.onlab.packet.IpPrefix;
34 +import org.onlab.packet.MacAddress;
34 import org.onlab.util.KryoNamespace; 35 import org.onlab.util.KryoNamespace;
35 import org.onosproject.config.NetworkConfigService; 36 import org.onosproject.config.NetworkConfigService;
36 import org.onosproject.core.ApplicationId; 37 import org.onosproject.core.ApplicationId;
37 import org.onosproject.core.CoreService; 38 import org.onosproject.core.CoreService;
38 import org.onosproject.net.DeviceId; 39 import org.onosproject.net.DeviceId;
39 -import org.onosproject.net.flow.DefaultFlowRule;
40 import org.onosproject.net.flow.DefaultTrafficSelector; 40 import org.onosproject.net.flow.DefaultTrafficSelector;
41 import org.onosproject.net.flow.DefaultTrafficTreatment; 41 import org.onosproject.net.flow.DefaultTrafficTreatment;
42 -import org.onosproject.net.flow.FlowRule;
43 -import org.onosproject.net.flow.FlowRuleOperations;
44 import org.onosproject.net.flow.FlowRuleService; 42 import org.onosproject.net.flow.FlowRuleService;
45 import org.onosproject.net.flow.TrafficSelector; 43 import org.onosproject.net.flow.TrafficSelector;
46 import org.onosproject.net.flow.TrafficTreatment; 44 import org.onosproject.net.flow.TrafficTreatment;
47 import org.onosproject.net.flow.criteria.Criteria; 45 import org.onosproject.net.flow.criteria.Criteria;
48 import org.onosproject.net.flowobjective.DefaultFilteringObjective; 46 import org.onosproject.net.flowobjective.DefaultFilteringObjective;
47 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
48 +import org.onosproject.net.flowobjective.DefaultNextObjective;
49 import org.onosproject.net.flowobjective.FilteringObjective; 49 import org.onosproject.net.flowobjective.FilteringObjective;
50 import org.onosproject.net.flowobjective.FlowObjectiveService; 50 import org.onosproject.net.flowobjective.FlowObjectiveService;
51 -import org.onosproject.net.group.DefaultGroupBucket; 51 +import org.onosproject.net.flowobjective.ForwardingObjective;
52 -import org.onosproject.net.group.DefaultGroupDescription; 52 +import org.onosproject.net.flowobjective.NextObjective;
53 -import org.onosproject.net.group.DefaultGroupKey;
54 -import org.onosproject.net.group.Group;
55 -import org.onosproject.net.group.GroupBucket;
56 -import org.onosproject.net.group.GroupBuckets;
57 -import org.onosproject.net.group.GroupDescription;
58 -import org.onosproject.net.group.GroupEvent;
59 -import org.onosproject.net.group.GroupListener;
60 import org.onosproject.net.group.GroupService; 53 import org.onosproject.net.group.GroupService;
61 import org.onosproject.net.packet.PacketService; 54 import org.onosproject.net.packet.PacketService;
62 import org.onosproject.routing.FibEntry; 55 import org.onosproject.routing.FibEntry;
...@@ -74,7 +67,8 @@ import java.util.Collections; ...@@ -74,7 +67,8 @@ import java.util.Collections;
74 import java.util.HashMap; 67 import java.util.HashMap;
75 import java.util.Map; 68 import java.util.Map;
76 import java.util.Set; 69 import java.util.Set;
77 -import java.util.stream.Collectors; 70 +
71 +import static org.onlab.util.Tools.delay;
78 72
79 /** 73 /**
80 * BgpRouter component. 74 * BgpRouter component.
...@@ -124,7 +118,7 @@ public class BgpRouter { ...@@ -124,7 +118,7 @@ public class BgpRouter {
124 private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap(); 118 private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap();
125 119
126 // Mapping from next hop IP to next hop object containing group info 120 // Mapping from next hop IP to next hop object containing group info
127 - private final Map<IpAddress, NextHop> nextHops = Maps.newHashMap(); 121 + private final Map<IpAddress, Integer> nextHops = Maps.newHashMap();
128 122
129 // Stores FIB updates that are waiting for groups to be set up 123 // Stores FIB updates that are waiting for groups to be set up
130 private final Multimap<NextHopGroupKey, FibEntry> pendingUpdates = HashMultimap.create(); 124 private final Multimap<NextHopGroupKey, FibEntry> pendingUpdates = HashMultimap.create();
...@@ -136,7 +130,7 @@ public class BgpRouter { ...@@ -136,7 +130,7 @@ public class BgpRouter {
136 // learned from config 130 // learned from config
137 private DeviceId ctrlDeviceId; 131 private DeviceId ctrlDeviceId;
138 132
139 - private final GroupListener groupListener = new InternalGroupListener(); 133 + //private final GroupListener groupListener = new InternalGroupListener();
140 134
141 private TunnellingConnectivityManager connectivityManager; 135 private TunnellingConnectivityManager connectivityManager;
142 136
...@@ -160,7 +154,7 @@ public class BgpRouter { ...@@ -160,7 +154,7 @@ public class BgpRouter {
160 appId = coreService.registerApplication(BGP_ROUTER_APP); 154 appId = coreService.registerApplication(BGP_ROUTER_APP);
161 getDeviceConfiguration(configService.getBgpSpeakers()); 155 getDeviceConfiguration(configService.getBgpSpeakers());
162 156
163 - groupService.addListener(groupListener); 157 + //groupService.addListener(groupListener);
164 158
165 processIntfFilters(true, configService.getInterfaces()); 159 processIntfFilters(true, configService.getInterfaces());
166 160
...@@ -179,6 +173,14 @@ public class BgpRouter { ...@@ -179,6 +173,14 @@ public class BgpRouter {
179 icmpHandler.start(); 173 icmpHandler.start();
180 174
181 log.info("BgpRouter started"); 175 log.info("BgpRouter started");
176 +
177 + delay(1000);
178 +
179 + FibEntry fibEntry = new FibEntry(Ip4Prefix.valueOf("10.1.0.0/16"),
180 + Ip4Address.valueOf("192.168.10.1"),
181 + MacAddress.valueOf("DE:AD:BE:EF:FE:ED"));
182 + FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
183 + updateFibEntry(Collections.singletonList(fibUpdate));
182 } 184 }
183 185
184 @Deactivate 186 @Deactivate
...@@ -188,7 +190,7 @@ public class BgpRouter { ...@@ -188,7 +190,7 @@ public class BgpRouter {
188 icmpHandler.stop(); 190 icmpHandler.stop();
189 processIntfFilters(false, configService.getInterfaces()); 191 processIntfFilters(false, configService.getInterfaces());
190 192
191 - groupService.removeListener(groupListener); 193 + //groupService.removeListener(groupListener);
192 194
193 log.info("BgpRouter stopped"); 195 log.info("BgpRouter stopped");
194 } 196 }
...@@ -213,16 +215,18 @@ public class BgpRouter { ...@@ -213,16 +215,18 @@ public class BgpRouter {
213 } 215 }
214 216
215 private void updateFibEntry(Collection<FibUpdate> updates) { 217 private void updateFibEntry(Collection<FibUpdate> updates) {
216 - Map<FibEntry, Group> toInstall = new HashMap<>(updates.size()); 218 + Map<FibEntry, Integer> toInstall = new HashMap<>(updates.size());
217 219
218 for (FibUpdate update : updates) { 220 for (FibUpdate update : updates) {
219 FibEntry entry = update.entry(); 221 FibEntry entry = update.entry();
220 222
221 addNextHop(entry); 223 addNextHop(entry);
222 224
223 - Group group; 225 + Integer nextId;
224 synchronized (pendingUpdates) { 226 synchronized (pendingUpdates) {
225 - NextHop nextHop = nextHops.get(entry.nextHopIp()); 227 + nextId = nextHops.get(entry.nextHopIp());
228 +
229 + /*
226 group = groupService.getGroup(deviceId, 230 group = groupService.getGroup(deviceId,
227 new DefaultGroupKey( 231 new DefaultGroupKey(
228 appKryo.serialize(nextHop.group()))); 232 appKryo.serialize(nextHop.group())));
...@@ -231,66 +235,70 @@ public class BgpRouter { ...@@ -231,66 +235,70 @@ public class BgpRouter {
231 log.debug("Adding pending flow {}", update.entry()); 235 log.debug("Adding pending flow {}", update.entry());
232 pendingUpdates.put(nextHop.group(), update.entry()); 236 pendingUpdates.put(nextHop.group(), update.entry());
233 continue; 237 continue;
234 - } 238 + }*/
235 } 239 }
236 240
237 - toInstall.put(update.entry(), group); 241 + toInstall.put(update.entry(), nextId);
238 } 242 }
239 243
240 installFlows(toInstall); 244 installFlows(toInstall);
241 } 245 }
242 246
243 - private void installFlows(Map<FibEntry, Group> entriesToInstall) { 247 + private void installFlows(Map<FibEntry, Integer> entriesToInstall) {
244 - FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
245 248
246 - for (Map.Entry<FibEntry, Group> entry : entriesToInstall.entrySet()) { 249 + for (Map.Entry<FibEntry, Integer> entry : entriesToInstall.entrySet()) {
247 FibEntry fibEntry = entry.getKey(); 250 FibEntry fibEntry = entry.getKey();
248 - Group group = entry.getValue(); 251 + Integer nextId = entry.getValue();
252 +
253 + flowObjectiveService.forward(deviceId,
254 + generateRibFlowRule(fibEntry.prefix(), nextId).add());
249 255
250 - FlowRule flowRule = generateRibFlowRule(fibEntry.prefix(), group);
251 256
252 - builder.add(flowRule);
253 } 257 }
258 + log.info("Sending flow forwarding objective");
254 259
255 - flowService.apply(builder.build());
256 } 260 }
257 261
258 private synchronized void deleteFibEntry(Collection<FibUpdate> withdraws) { 262 private synchronized void deleteFibEntry(Collection<FibUpdate> withdraws) {
259 - FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
260 263
261 for (FibUpdate update : withdraws) { 264 for (FibUpdate update : withdraws) {
262 FibEntry entry = update.entry(); 265 FibEntry entry = update.entry();
266 + Integer nextId = nextHops.get(entry.nextHopIp());
263 267
264 - Group group = deleteNextHop(entry.prefix()); 268 + /*Group group = deleteNextHop(entry.prefix());
265 if (group == null) { 269 if (group == null) {
266 log.warn("Group not found when deleting {}", entry); 270 log.warn("Group not found when deleting {}", entry);
267 return; 271 return;
268 - } 272 + }*/
269 273
270 - FlowRule flowRule = generateRibFlowRule(entry.prefix(), group); 274 + flowObjectiveService.forward(deviceId,
275 + generateRibFlowRule(entry.prefix(), nextId).remove());
271 276
272 - builder.remove(flowRule);
273 } 277 }
274 278
275 - flowService.apply(builder.build());
276 } 279 }
277 280
278 - private FlowRule generateRibFlowRule(IpPrefix prefix, Group group) { 281 + private ForwardingObjective.Builder generateRibFlowRule(IpPrefix prefix, Integer nextId) {
279 TrafficSelector selector = DefaultTrafficSelector.builder() 282 TrafficSelector selector = DefaultTrafficSelector.builder()
280 .matchEthType(Ethernet.TYPE_IPV4) 283 .matchEthType(Ethernet.TYPE_IPV4)
281 .matchIPDst(prefix) 284 .matchIPDst(prefix)
282 .build(); 285 .build();
283 286
284 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
285 - .group(group.id())
286 - .build();
287 287
288 288
289 int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET; 289 int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
290 290
291 - return new DefaultFlowRule(deviceId, selector, treatment, 291 + ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder()
292 - priority, appId, 0, true, 292 + .fromApp(appId)
293 - FlowRule.Type.IP); 293 + .makePermanent()
294 + .nextStep(nextId)
295 + .withSelector(selector)
296 + .withPriority(priority)
297 + .withFlag(ForwardingObjective.Flag.SPECIFIC);
298 +
299 + return fwdBuilder;
300 +
301 +
294 } 302 }
295 303
296 private synchronized void addNextHop(FibEntry entry) { 304 private synchronized void addNextHop(FibEntry entry) {
...@@ -317,6 +325,16 @@ public class BgpRouter { ...@@ -317,6 +325,16 @@ public class BgpRouter {
317 .setOutput(egressIntf.connectPoint().port()) 325 .setOutput(egressIntf.connectPoint().port())
318 .build(); 326 .build();
319 327
328 + NextObjective nextObjective = DefaultNextObjective.builder()
329 + .withId(entry.hashCode())
330 + .addTreatment(treatment)
331 + .withType(NextObjective.Type.SIMPLE)
332 + .fromApp(appId)
333 + .add();
334 +
335 + flowObjectiveService.next(deviceId, nextObjective);
336 +
337 + /*
320 GroupBucket bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment); 338 GroupBucket bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
321 339
322 GroupDescription groupDescription 340 GroupDescription groupDescription
...@@ -328,15 +346,16 @@ public class BgpRouter { ...@@ -328,15 +346,16 @@ public class BgpRouter {
328 appId); 346 appId);
329 347
330 groupService.addGroup(groupDescription); 348 groupService.addGroup(groupDescription);
349 + */
331 350
332 - nextHops.put(nextHop.ip(), nextHop); 351 + nextHops.put(nextHop.ip(), entry.hashCode());
333 352
334 } 353 }
335 354
336 nextHopsCount.add(entry.nextHopIp()); 355 nextHopsCount.add(entry.nextHopIp());
337 } 356 }
338 357
339 - private synchronized Group deleteNextHop(IpPrefix prefix) { 358 + /*private synchronized Group deleteNextHop(IpPrefix prefix) {
340 IpAddress nextHopIp = prefixToNextHop.remove(prefix); 359 IpAddress nextHopIp = prefixToNextHop.remove(prefix);
341 NextHop nextHop = nextHops.get(nextHopIp); 360 NextHop nextHop = nextHops.get(nextHopIp);
342 if (nextHop == null) { 361 if (nextHop == null) {
...@@ -349,7 +368,7 @@ public class BgpRouter { ...@@ -349,7 +368,7 @@ public class BgpRouter {
349 serialize(nextHop.group()))); 368 serialize(nextHop.group())));
350 369
351 // FIXME disabling group deletes for now until we verify the logic is OK 370 // FIXME disabling group deletes for now until we verify the logic is OK
352 - /*if (nextHopsCount.remove(nextHopIp, 1) <= 1) { 371 + *//*if (nextHopsCount.remove(nextHopIp, 1) <= 1) {
353 // There was one or less next hops, so there are now none 372 // There was one or less next hops, so there are now none
354 373
355 log.debug("removing group for next hop {}", nextHop); 374 log.debug("removing group for next hop {}", nextHop);
...@@ -359,10 +378,10 @@ public class BgpRouter { ...@@ -359,10 +378,10 @@ public class BgpRouter {
359 groupService.removeGroup(deviceId, 378 groupService.removeGroup(deviceId,
360 new DefaultGroupKey(appKryo.build().serialize(nextHop.group())), 379 new DefaultGroupKey(appKryo.build().serialize(nextHop.group())),
361 appId); 380 appId);
362 - }*/ 381 + }*//*
363 382
364 return group; 383 return group;
365 - } 384 + }*/
366 385
367 private class InternalFibListener implements FibListener { 386 private class InternalFibListener implements FibListener {
368 387
...@@ -385,12 +404,11 @@ public class BgpRouter { ...@@ -385,12 +404,11 @@ public class BgpRouter {
385 .forEach(ipaddr -> fob.addCondition( 404 .forEach(ipaddr -> fob.addCondition(
386 Criteria.matchIPDst(ipaddr.subnetAddress()))); 405 Criteria.matchIPDst(ipaddr.subnetAddress())));
387 fob.permit().fromApp(appId); 406 fob.permit().fromApp(appId);
388 - flowObjectiveService.filter(deviceId, 407 + flowObjectiveService.filter(deviceId, fob.add());
389 - Collections.singletonList(fob.add()));
390 } 408 }
391 } 409 }
392 410
393 - private class InternalGroupListener implements GroupListener { 411 + /* private class InternalGroupListener implements GroupListener {
394 412
395 @Override 413 @Override
396 public void event(GroupEvent event) { 414 public void event(GroupEvent event) {
...@@ -412,5 +430,5 @@ public class BgpRouter { ...@@ -412,5 +430,5 @@ public class BgpRouter {
412 } 430 }
413 } 431 }
414 } 432 }
415 - } 433 + }*/
416 } 434 }
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.behaviour;
17 +
18 +/**
19 + * Default implementation of a next group.
20 + */
21 +public class DefaultNextGroup implements NextGroup {
22 +
23 + private final byte[] data;
24 +
25 + public DefaultNextGroup(byte[] data) {
26 + this.data = data;
27 + }
28 +
29 + @Override
30 + public byte[] data() {
31 + return data;
32 + }
33 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.behaviour;
17 +
18 +/**
19 + * Opaque data type for carrying group-like information.
20 + * Only relevant to a pipeliner driver.
21 + */
22 +public interface NextGroup {
23 +
24 + /**
25 + * Serialized form of the next group.
26 + * @return a byte array.
27 + */
28 + byte[] data();
29 +
30 +}
...@@ -21,9 +21,6 @@ import org.onosproject.net.flowobjective.FilteringObjective; ...@@ -21,9 +21,6 @@ import org.onosproject.net.flowobjective.FilteringObjective;
21 import org.onosproject.net.flowobjective.ForwardingObjective; 21 import org.onosproject.net.flowobjective.ForwardingObjective;
22 import org.onosproject.net.flowobjective.NextObjective; 22 import org.onosproject.net.flowobjective.NextObjective;
23 23
24 -import java.util.Collection;
25 -import java.util.concurrent.Future;
26 -
27 /** 24 /**
28 * Behaviour for handling various pipelines. 25 * Behaviour for handling various pipelines.
29 */ 26 */
...@@ -40,24 +37,21 @@ public interface Pipeliner extends HandlerBehaviour { ...@@ -40,24 +37,21 @@ public interface Pipeliner extends HandlerBehaviour {
40 /** 37 /**
41 * Installs the filtering rules onto the device. 38 * Installs the filtering rules onto the device.
42 * 39 *
43 - * @param filterObjectives the collection of filters 40 + * @param filterObjective a filtering objective
44 - * @return a future indicating the success of the operation
45 */ 41 */
46 - Future<Boolean> filter(Collection<FilteringObjective> filterObjectives); 42 + void filter(FilteringObjective filterObjective);
47 43
48 /** 44 /**
49 * Installs the forwarding rules onto the device. 45 * Installs the forwarding rules onto the device.
50 * 46 *
51 - * @param forwardObjectives the collection of forwarding objectives 47 + * @param forwardObjective a forwarding objective
52 - * @return a future indicating the success of the operation
53 */ 48 */
54 - Future<Boolean> forward(Collection<ForwardingObjective> forwardObjectives); 49 + void forward(ForwardingObjective forwardObjective);
55 50
56 /** 51 /**
57 * Installs the next hop elements into the device. 52 * Installs the next hop elements into the device.
58 * 53 *
59 - * @param nextObjectives the collection of next objectives 54 + * @param nextObjective a next objectives
60 - * @return a future indicating the success of the operation
61 */ 55 */
62 - Future<Boolean> next(Collection<NextObjective> nextObjectives); 56 + void next(NextObjective nextObjective);
63 } 57 }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.net.behaviour; 16 package org.onosproject.net.behaviour;
17 17
18 import org.onlab.osgi.ServiceDirectory; 18 import org.onlab.osgi.ServiceDirectory;
19 +import org.onosproject.net.flowobjective.FlowObjectiveStore;
19 20
20 /** 21 /**
21 * Processing context and supporting services for the pipeline behaviour. 22 * Processing context and supporting services for the pipeline behaviour.
...@@ -30,5 +31,11 @@ public interface PipelinerContext { ...@@ -30,5 +31,11 @@ public interface PipelinerContext {
30 */ 31 */
31 ServiceDirectory directory(); 32 ServiceDirectory directory();
32 33
34 + /**
35 + * Returns the Objective Store where data can be stored and retrieved.
36 + * @return the flow objective store
37 + */
38 + FlowObjectiveStore store();
39 +
33 // TODO: add means to store and access shared state 40 // TODO: add means to store and access shared state
34 } 41 }
......
...@@ -23,6 +23,7 @@ import org.onosproject.net.flow.criteria.Criterion; ...@@ -23,6 +23,7 @@ import org.onosproject.net.flow.criteria.Criterion;
23 import java.util.Collection; 23 import java.util.Collection;
24 import java.util.List; 24 import java.util.List;
25 import java.util.Objects; 25 import java.util.Objects;
26 +import java.util.Optional;
26 27
27 import static com.google.common.base.Preconditions.checkArgument; 28 import static com.google.common.base.Preconditions.checkArgument;
28 import static com.google.common.base.Preconditions.checkNotNull; 29 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -42,6 +43,7 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -42,6 +43,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
42 private final List<Criterion> conditions; 43 private final List<Criterion> conditions;
43 private final int id; 44 private final int id;
44 private final Operation op; 45 private final Operation op;
46 + private final Optional<ObjectiveContext> context;
45 47
46 private DefaultFilteringObjective(Type type, boolean permanent, int timeout, 48 private DefaultFilteringObjective(Type type, boolean permanent, int timeout,
47 ApplicationId appId, int priority, Criterion key, 49 ApplicationId appId, int priority, Criterion key,
...@@ -54,6 +56,25 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -54,6 +56,25 @@ public final class DefaultFilteringObjective implements FilteringObjective {
54 this.priority = priority; 56 this.priority = priority;
55 this.conditions = conditions; 57 this.conditions = conditions;
56 this.op = op; 58 this.op = op;
59 + this.context = Optional.empty();
60 +
61 + this.id = Objects.hash(type, key, conditions, permanent,
62 + timeout, appId, priority);
63 + }
64 +
65 + public DefaultFilteringObjective(Type type, boolean permanent, int timeout,
66 + ApplicationId appId, int priority, Criterion key,
67 + List<Criterion> conditions,
68 + ObjectiveContext context, Operation op) {
69 + this.key = key;
70 + this.type = type;
71 + this.permanent = permanent;
72 + this.timeout = timeout;
73 + this.appId = appId;
74 + this.priority = priority;
75 + this.conditions = conditions;
76 + this.op = op;
77 + this.context = Optional.ofNullable(context);
57 78
58 this.id = Objects.hash(type, key, conditions, permanent, 79 this.id = Objects.hash(type, key, conditions, permanent,
59 timeout, appId, priority); 80 timeout, appId, priority);
...@@ -104,6 +125,11 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -104,6 +125,11 @@ public final class DefaultFilteringObjective implements FilteringObjective {
104 return op; 125 return op;
105 } 126 }
106 127
128 + @Override
129 + public Optional<ObjectiveContext> context() {
130 + return context;
131 + }
132 +
107 /** 133 /**
108 * Returns a new builder. 134 * Returns a new builder.
109 * 135 *
...@@ -201,6 +227,31 @@ public final class DefaultFilteringObjective implements FilteringObjective { ...@@ -201,6 +227,31 @@ public final class DefaultFilteringObjective implements FilteringObjective {
201 227
202 } 228 }
203 229
230 + @Override
231 + public FilteringObjective add(ObjectiveContext context) {
232 + List<Criterion> conditions = listBuilder.build();
233 + checkNotNull(type, "Must have a type.");
234 + checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
235 + checkNotNull(appId, "Must supply an application id");
236 +
237 + return new DefaultFilteringObjective(type, permanent, timeout,
238 + appId, priority, key, conditions,
239 + context, Operation.ADD);
240 + }
241 +
242 + @Override
243 + public FilteringObjective remove(ObjectiveContext context) {
244 + List<Criterion> conditions = listBuilder.build();
245 + checkNotNull(type, "Must have a type.");
246 + checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
247 + checkNotNull(appId, "Must supply an application id");
248 +
249 +
250 + return new DefaultFilteringObjective(type, permanent, timeout,
251 + appId, priority, key, conditions,
252 + context, Operation.REMOVE);
253 + }
254 +
204 255
205 } 256 }
206 257
......
...@@ -20,6 +20,7 @@ import org.onosproject.net.flow.TrafficSelector; ...@@ -20,6 +20,7 @@ import org.onosproject.net.flow.TrafficSelector;
20 import org.onosproject.net.flow.TrafficTreatment; 20 import org.onosproject.net.flow.TrafficTreatment;
21 21
22 import java.util.Objects; 22 import java.util.Objects;
23 +import java.util.Optional;
23 24
24 import static com.google.common.base.Preconditions.checkArgument; 25 import static com.google.common.base.Preconditions.checkArgument;
25 import static com.google.common.base.Preconditions.checkNotNull; 26 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -38,6 +39,7 @@ public final class DefaultForwardingObjective implements ForwardingObjective { ...@@ -38,6 +39,7 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
38 private final int nextId; 39 private final int nextId;
39 private final TrafficTreatment treatment; 40 private final TrafficTreatment treatment;
40 private final Operation op; 41 private final Operation op;
42 + private final Optional<ObjectiveContext> context;
41 43
42 private final int id; 44 private final int id;
43 45
...@@ -55,6 +57,29 @@ public final class DefaultForwardingObjective implements ForwardingObjective { ...@@ -55,6 +57,29 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
55 this.nextId = nextId; 57 this.nextId = nextId;
56 this.treatment = treatment; 58 this.treatment = treatment;
57 this.op = op; 59 this.op = op;
60 + this.context = Optional.empty();
61 +
62 + this.id = Objects.hash(selector, flag, permanent,
63 + timeout, appId, priority, nextId,
64 + treatment, op);
65 + }
66 +
67 + private DefaultForwardingObjective(TrafficSelector selector,
68 + Flag flag, boolean permanent,
69 + int timeout, ApplicationId appId,
70 + int priority, int nextId,
71 + TrafficTreatment treatment,
72 + ObjectiveContext context, Operation op) {
73 + this.selector = selector;
74 + this.flag = flag;
75 + this.permanent = permanent;
76 + this.timeout = timeout;
77 + this.appId = appId;
78 + this.priority = priority;
79 + this.nextId = nextId;
80 + this.treatment = treatment;
81 + this.op = op;
82 + this.context = Optional.ofNullable(context);
58 83
59 this.id = Objects.hash(selector, flag, permanent, 84 this.id = Objects.hash(selector, flag, permanent,
60 timeout, appId, priority, nextId, 85 timeout, appId, priority, nextId,
...@@ -113,6 +138,11 @@ public final class DefaultForwardingObjective implements ForwardingObjective { ...@@ -113,6 +138,11 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
113 return op; 138 return op;
114 } 139 }
115 140
141 + @Override
142 + public Optional<ObjectiveContext> context() {
143 + return context;
144 + }
145 +
116 /** 146 /**
117 * Returns a new builder. 147 * Returns a new builder.
118 * 148 *
...@@ -186,7 +216,7 @@ public final class DefaultForwardingObjective implements ForwardingObjective { ...@@ -186,7 +216,7 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
186 public ForwardingObjective add() { 216 public ForwardingObjective add() {
187 checkNotNull(selector, "Must have a selector"); 217 checkNotNull(selector, "Must have a selector");
188 checkNotNull(flag, "A flag must be set"); 218 checkNotNull(flag, "A flag must be set");
189 - checkArgument(nextId != null && treatment != null, "Must supply at " + 219 + checkArgument(nextId != null || treatment != null, "Must supply at " +
190 "least a treatment and/or a nextId"); 220 "least a treatment and/or a nextId");
191 checkNotNull(appId, "Must supply an application id"); 221 checkNotNull(appId, "Must supply an application id");
192 return new DefaultForwardingObjective(selector, flag, permanent, 222 return new DefaultForwardingObjective(selector, flag, permanent,
...@@ -198,12 +228,38 @@ public final class DefaultForwardingObjective implements ForwardingObjective { ...@@ -198,12 +228,38 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
198 public ForwardingObjective remove() { 228 public ForwardingObjective remove() {
199 checkNotNull(selector, "Must have a selector"); 229 checkNotNull(selector, "Must have a selector");
200 checkNotNull(flag, "A flag must be set"); 230 checkNotNull(flag, "A flag must be set");
201 - checkArgument(nextId != null && treatment != null, "Must supply at " + 231 + checkArgument(nextId != null || treatment != null, "Must supply at " +
202 "least a treatment and/or a nextId"); 232 "least a treatment and/or a nextId");
203 checkNotNull(appId, "Must supply an application id"); 233 checkNotNull(appId, "Must supply an application id");
204 return new DefaultForwardingObjective(selector, flag, permanent, 234 return new DefaultForwardingObjective(selector, flag, permanent,
205 timeout, appId, priority, 235 timeout, appId, priority,
206 nextId, treatment, Operation.REMOVE); 236 nextId, treatment, Operation.REMOVE);
207 } 237 }
238 +
239 + @Override
240 + public ForwardingObjective add(ObjectiveContext context) {
241 + checkNotNull(selector, "Must have a selector");
242 + checkNotNull(flag, "A flag must be set");
243 + checkArgument(nextId != null || treatment != null, "Must supply at " +
244 + "least a treatment and/or a nextId");
245 + checkNotNull(appId, "Must supply an application id");
246 + return new DefaultForwardingObjective(selector, flag, permanent,
247 + timeout, appId, priority,
248 + nextId, treatment,
249 + context, Operation.ADD);
250 + }
251 +
252 + @Override
253 + public ForwardingObjective remove(ObjectiveContext context) {
254 + checkNotNull(selector, "Must have a selector");
255 + checkNotNull(flag, "A flag must be set");
256 + checkArgument(nextId != null || treatment != null, "Must supply at " +
257 + "least a treatment and/or a nextId");
258 + checkNotNull(appId, "Must supply an application id");
259 + return new DefaultForwardingObjective(selector, flag, permanent,
260 + timeout, appId, priority,
261 + nextId, treatment,
262 + context, Operation.REMOVE);
263 + }
208 } 264 }
209 } 265 }
......
...@@ -21,6 +21,7 @@ import org.onosproject.net.flow.TrafficTreatment; ...@@ -21,6 +21,7 @@ import org.onosproject.net.flow.TrafficTreatment;
21 21
22 import java.util.Collection; 22 import java.util.Collection;
23 import java.util.List; 23 import java.util.List;
24 +import java.util.Optional;
24 25
25 import static com.google.common.base.Preconditions.checkArgument; 26 import static com.google.common.base.Preconditions.checkArgument;
26 import static com.google.common.base.Preconditions.checkNotNull; 27 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -34,13 +35,28 @@ public final class DefaultNextObjective implements NextObjective { ...@@ -34,13 +35,28 @@ public final class DefaultNextObjective implements NextObjective {
34 private final ApplicationId appId; 35 private final ApplicationId appId;
35 private final Type type; 36 private final Type type;
36 private final Integer id; 37 private final Integer id;
38 + private final Operation op;
39 + private final Optional<ObjectiveContext> context;
37 40
38 private DefaultNextObjective(Integer id, List<TrafficTreatment> treatments, 41 private DefaultNextObjective(Integer id, List<TrafficTreatment> treatments,
39 - ApplicationId appId, Type type) { 42 + ApplicationId appId, Type type, Operation op) {
40 this.treatments = treatments; 43 this.treatments = treatments;
41 this.appId = appId; 44 this.appId = appId;
42 this.type = type; 45 this.type = type;
43 this.id = id; 46 this.id = id;
47 + this.op = op;
48 + this.context = Optional.empty();
49 + }
50 +
51 + private DefaultNextObjective(Integer id, List<TrafficTreatment> treatments,
52 + ApplicationId appId, ObjectiveContext context,
53 + Type type, Operation op) {
54 + this.treatments = treatments;
55 + this.appId = appId;
56 + this.type = type;
57 + this.id = id;
58 + this.op = op;
59 + this.context = Optional.ofNullable(context);
44 } 60 }
45 61
46 @Override 62 @Override
...@@ -80,7 +96,12 @@ public final class DefaultNextObjective implements NextObjective { ...@@ -80,7 +96,12 @@ public final class DefaultNextObjective implements NextObjective {
80 96
81 @Override 97 @Override
82 public Operation op() { 98 public Operation op() {
83 - throw new UnsupportedOperationException("Next Objective has no operation"); 99 + return op;
100 + }
101 +
102 + @Override
103 + public Optional<ObjectiveContext> context() {
104 + return context;
84 } 105 }
85 106
86 /** 107 /**
...@@ -101,8 +122,6 @@ public final class DefaultNextObjective implements NextObjective { ...@@ -101,8 +122,6 @@ public final class DefaultNextObjective implements NextObjective {
101 private final ImmutableList.Builder<TrafficTreatment> listBuilder 122 private final ImmutableList.Builder<TrafficTreatment> listBuilder
102 = ImmutableList.builder(); 123 = ImmutableList.builder();
103 124
104 -
105 -
106 @Override 125 @Override
107 public NextObjective.Builder withId(int nextId) { 126 public NextObjective.Builder withId(int nextId) {
108 this.id = nextId; 127 this.id = nextId;
...@@ -143,7 +162,7 @@ public final class DefaultNextObjective implements NextObjective { ...@@ -143,7 +162,7 @@ public final class DefaultNextObjective implements NextObjective {
143 } 162 }
144 163
145 @Override 164 @Override
146 - public Builder fromApp(ApplicationId appId) { 165 + public NextObjective.Builder fromApp(ApplicationId appId) {
147 this.appId = appId; 166 this.appId = appId;
148 return this; 167 return this;
149 } 168 }
...@@ -160,14 +179,49 @@ public final class DefaultNextObjective implements NextObjective { ...@@ -160,14 +179,49 @@ public final class DefaultNextObjective implements NextObjective {
160 } 179 }
161 180
162 @Override 181 @Override
163 - public NextObjective build() { 182 + public NextObjective add() {
183 + List<TrafficTreatment> treatments = listBuilder.build();
184 + checkNotNull(appId, "Must supply an application id");
185 + checkNotNull(id, "id cannot be null");
186 + checkNotNull(type, "The type cannot be null");
187 + checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
188 +
189 + return new DefaultNextObjective(id, treatments, appId, type, Operation.ADD);
190 + }
191 +
192 + @Override
193 + public NextObjective remove() {
194 + List<TrafficTreatment> treatments = listBuilder.build();
195 + checkNotNull(appId, "Must supply an application id");
196 + checkNotNull(id, "id cannot be null");
197 + checkNotNull(type, "The type cannot be null");
198 + checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
199 +
200 + return new DefaultNextObjective(id, treatments, appId, type, Operation.REMOVE);
201 + }
202 +
203 + @Override
204 + public NextObjective add(ObjectiveContext context) {
205 + List<TrafficTreatment> treatments = listBuilder.build();
206 + checkNotNull(appId, "Must supply an application id");
207 + checkNotNull(id, "id cannot be null");
208 + checkNotNull(type, "The type cannot be null");
209 + checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
210 +
211 + return new DefaultNextObjective(id, treatments, appId,
212 + context, type, Operation.ADD);
213 + }
214 +
215 + @Override
216 + public NextObjective remove(ObjectiveContext context) {
164 List<TrafficTreatment> treatments = listBuilder.build(); 217 List<TrafficTreatment> treatments = listBuilder.build();
165 checkNotNull(appId, "Must supply an application id"); 218 checkNotNull(appId, "Must supply an application id");
166 checkNotNull(id, "id cannot be null"); 219 checkNotNull(id, "id cannot be null");
167 checkNotNull(type, "The type cannot be null"); 220 checkNotNull(type, "The type cannot be null");
168 checkArgument(!treatments.isEmpty(), "Must have at least one treatment"); 221 checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
169 222
170 - return new DefaultNextObjective(id, treatments, appId, type); 223 + return new DefaultNextObjective(id, treatments, appId,
224 + context, type, Operation.REMOVE);
171 } 225 }
172 } 226 }
173 } 227 }
......
...@@ -114,6 +114,24 @@ public interface FilteringObjective extends Objective { ...@@ -114,6 +114,24 @@ public interface FilteringObjective extends Objective {
114 */ 114 */
115 public FilteringObjective remove(); 115 public FilteringObjective remove();
116 116
117 + /**
118 + * Builds the filtering objective that will be added.
119 + * The context will be used to notify the calling application.
120 + *
121 + * @param context an objective context
122 + * @return a filtering objective
123 + */
124 + public FilteringObjective add(ObjectiveContext context);
125 +
126 + /**
127 + * Builds the filtering objective that will be removed.
128 + * The context will be used to notify the calling application.
129 + *
130 + * @param context an objective context
131 + * @return a filtering objective
132 + */
133 + public FilteringObjective remove(ObjectiveContext context);
134 +
117 135
118 } 136 }
119 137
......
...@@ -17,9 +17,6 @@ package org.onosproject.net.flowobjective; ...@@ -17,9 +17,6 @@ package org.onosproject.net.flowobjective;
17 17
18 import org.onosproject.net.DeviceId; 18 import org.onosproject.net.DeviceId;
19 19
20 -import java.util.Collection;
21 -import java.util.concurrent.Future;
22 -
23 /** 20 /**
24 * Service for programming data plane flow rules in manner independent of 21 * Service for programming data plane flow rules in manner independent of
25 * specific device table pipeline configuration. 22 * specific device table pipeline configuration.
...@@ -30,27 +27,24 @@ public interface FlowObjectiveService { ...@@ -30,27 +27,24 @@ public interface FlowObjectiveService {
30 * Installs the filtering rules onto the specified device. 27 * Installs the filtering rules onto the specified device.
31 * 28 *
32 * @param deviceId device identifier 29 * @param deviceId device identifier
33 - * @param filteringObjectives the collection of filters 30 + * @param filteringObjective the filtering objective
34 - * @return a future indicating the success of the operation
35 */ 31 */
36 - Future<Boolean> filter(DeviceId deviceId, Collection<FilteringObjective> filteringObjectives); 32 + void filter(DeviceId deviceId, FilteringObjective filteringObjective);
37 33
38 /** 34 /**
39 * Installs the forwarding rules onto the specified device. 35 * Installs the forwarding rules onto the specified device.
40 * 36 *
41 * @param deviceId device identifier 37 * @param deviceId device identifier
42 - * @param forwardingObjectives the collection of forwarding objectives 38 + * @param forwardingObjective the forwarding objective
43 - * @return a future indicating the success of the operation
44 */ 39 */
45 - Future<Boolean> forward(DeviceId deviceId, Collection<ForwardingObjective> forwardingObjectives); 40 + void forward(DeviceId deviceId, ForwardingObjective forwardingObjective);
46 41
47 /** 42 /**
48 * Installs the next hop elements into the specified device. 43 * Installs the next hop elements into the specified device.
49 * 44 *
50 * @param deviceId device identifier 45 * @param deviceId device identifier
51 - * @param nextObjectives the collection of next objectives 46 + * @param nextObjective a next objective
52 - * @return a future indicating the success of the operation
53 */ 47 */
54 - Future<Boolean> next(DeviceId deviceId, Collection<NextObjective> nextObjectives); 48 + void next(DeviceId deviceId, NextObjective nextObjective);
55 49
56 } 50 }
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.flowobjective;
17 +
18 +import org.onosproject.net.behaviour.NextGroup;
19 +import org.onosproject.store.Store;
20 +
21 +/**
22 + * The flow objective store.
23 + */
24 +public interface FlowObjectiveStore
25 + extends Store<ObjectiveEvent, FlowObjectiveStoreDelegate> {
26 +
27 + /**
28 + * Adds a NextGroup to the store.
29 + *
30 + * @param nextId an integer
31 + * @param group a next group opaque object
32 + */
33 + void putNextGroup(Integer nextId, NextGroup group);
34 +
35 + /**
36 + * Fetch a next group from the store.
37 + * @param nextId an integer
38 + * @return a next group
39 + */
40 + NextGroup getNextGroup(Integer nextId);
41 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.flowobjective;
17 +
18 +import org.onosproject.store.StoreDelegate;
19 +
20 +/**
21 + * Flow Objective store delegate abstraction.
22 + */
23 +public interface FlowObjectiveStoreDelegate extends StoreDelegate<ObjectiveEvent> {
24 +}
...@@ -121,5 +121,23 @@ public interface ForwardingObjective extends Objective { ...@@ -121,5 +121,23 @@ public interface ForwardingObjective extends Objective {
121 * @return a forwarding objective. 121 * @return a forwarding objective.
122 */ 122 */
123 public ForwardingObjective remove(); 123 public ForwardingObjective remove();
124 +
125 + /**
126 + * Builds the forwarding objective that will be added.
127 + * The context will be used to notify the calling application.
128 + *
129 + * @param context an objective context
130 + * @return a forwarding objective
131 + */
132 + public ForwardingObjective add(ObjectiveContext context);
133 +
134 + /**
135 + * Builds the forwarding objective that will be removed.
136 + * The context will be used to notify the calling application.
137 + *
138 + * @param context an objective context
139 + * @return a forwarding objective
140 + */
141 + public ForwardingObjective remove(ObjectiveContext context);
124 } 142 }
125 } 143 }
......
...@@ -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.TrafficTreatment; 19 import org.onosproject.net.flow.TrafficTreatment;
19 20
20 import java.util.Collection; 21 import java.util.Collection;
...@@ -95,12 +96,40 @@ public interface NextObjective extends Objective { ...@@ -95,12 +96,40 @@ public interface NextObjective extends Objective {
95 */ 96 */
96 public Builder addTreatment(TrafficTreatment treatment); 97 public Builder addTreatment(TrafficTreatment treatment);
97 98
99 + @Override
100 + public Builder fromApp(ApplicationId appId);
101 +
102 + /**
103 + * Builds the next objective that will be added.
104 + *
105 + * @return a next objective
106 + */
107 + public NextObjective add();
108 +
109 + /**
110 + * Builds the next objective that will be removed.
111 + *
112 + * @return a next objective.
113 + */
114 + public NextObjective remove();
115 +
116 + /**
117 + * Builds the next objective that will be added.
118 + * The context will be used to notify the calling application.
119 + *
120 + * @param context an objective context
121 + * @return a next objective
122 + */
123 + public NextObjective add(ObjectiveContext context);
124 +
98 /** 125 /**
99 - * Builds a next step. 126 + * Builds the next objective that will be removed.
127 + * The context will be used to notify the calling application.
100 * 128 *
101 - * @return a next step 129 + * @param context an objective context
130 + * @return a next objective
102 */ 131 */
103 - public NextObjective build(); 132 + public NextObjective remove(ObjectiveContext context);
104 133
105 } 134 }
106 135
......
...@@ -17,6 +17,8 @@ package org.onosproject.net.flowobjective; ...@@ -17,6 +17,8 @@ package org.onosproject.net.flowobjective;
17 17
18 import org.onosproject.core.ApplicationId; 18 import org.onosproject.core.ApplicationId;
19 19
20 +import java.util.Optional;
21 +
20 /** 22 /**
21 * Base representation of an flow description. 23 * Base representation of an flow description.
22 */ 24 */
...@@ -84,6 +86,14 @@ public interface Objective { ...@@ -84,6 +86,14 @@ public interface Objective {
84 Operation op(); 86 Operation op();
85 87
86 /** 88 /**
89 + * Obtains an optional context.
90 + *
91 + * @return optional; which will be empty if there is no context.
92 + * Otherwise it will return the context.
93 + */
94 + Optional<ObjectiveContext> context();
95 +
96 + /**
87 * An objective builder. 97 * An objective builder.
88 */ 98 */
89 public interface Builder { 99 public interface Builder {
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.flowobjective;
17 +
18 +/**
19 + * The context of a objective that will become the subject of
20 + * the notification.
21 + *
22 + * Implementations of this class must be serializable.
23 + */
24 +public interface ObjectiveContext {
25 +
26 + default void onSuccess(Objective objective) {}
27 +
28 + default void onError(Objective objective, ObjectiveError error) {}
29 +
30 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.flowobjective;
17 +
18 +/**
19 + * Represents the set of errors possible when processing an objective.
20 + */
21 +public enum ObjectiveError {
22 +
23 + /**
24 + * The driver processing this objective does not know how to process it.
25 + */
26 + UNSUPPORTED,
27 +
28 + /**
29 + * The flow installation for this objective failed.
30 + */
31 + FLOWINSTALLATIONFAILED,
32 +
33 + /**
34 + * THe group installation for this objective failed.
35 + */
36 + GROUPINSTALLATIONFAILED,
37 +
38 + /**
39 + * The group was reported as installed but is not missing.
40 + */
41 + GROUPMISSING,
42 +
43 + /**
44 + * An unknown error occurred.
45 + */
46 + UNKNOWN
47 +}
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.net.flowobjective;
17 +
18 +import org.onosproject.event.AbstractEvent;
19 +
20 +/**
21 + * Describes a objective event.
22 + */
23 +public class ObjectiveEvent extends AbstractEvent<ObjectiveEvent.Type, Integer> {
24 +
25 + /**
26 + * Type of objective events.
27 + */
28 + public enum Type {
29 + /**
30 + * Signifies that the objective has been added to the store.
31 + */
32 + ADD,
33 +
34 + /**
35 + * Signifies that the objective has been removed.
36 + */
37 + REMOVE
38 + }
39 +
40 + /**
41 + * Creates an event of the given type for the specified objective id.
42 + *
43 + * @param type the type of the event
44 + * @param objective the objective id the event is about
45 + */
46 + public ObjectiveEvent(Type type, Integer objective) {
47 + super(type, objective);
48 + }
49 +
50 + /**
51 + * Creates an event of the given type for the specified objective id at the given
52 + * time.
53 + *
54 + * @param type the type of the event
55 + * @param objective the objective id the event is about
56 + * @param time the time of the event
57 + */
58 + public ObjectiveEvent(Type type, Integer objective, long time) {
59 + super(type, objective, time);
60 + }
61 +}
62 +
...@@ -17,7 +17,7 @@ package org.onosproject.net.flowobjective.impl; ...@@ -17,7 +17,7 @@ package org.onosproject.net.flowobjective.impl;
17 17
18 import com.google.common.collect.Lists; 18 import com.google.common.collect.Lists;
19 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
20 -import com.google.common.util.concurrent.Futures; 20 +import com.google.common.collect.Sets;
21 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
...@@ -43,9 +43,12 @@ import org.onosproject.net.driver.DriverService; ...@@ -43,9 +43,12 @@ import org.onosproject.net.driver.DriverService;
43 import org.onosproject.net.flow.FlowRuleService; 43 import org.onosproject.net.flow.FlowRuleService;
44 import org.onosproject.net.flowobjective.FilteringObjective; 44 import org.onosproject.net.flowobjective.FilteringObjective;
45 import org.onosproject.net.flowobjective.FlowObjectiveService; 45 import org.onosproject.net.flowobjective.FlowObjectiveService;
46 +import org.onosproject.net.flowobjective.FlowObjectiveStore;
47 +import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
46 import org.onosproject.net.flowobjective.ForwardingObjective; 48 import org.onosproject.net.flowobjective.ForwardingObjective;
47 import org.onosproject.net.flowobjective.NextObjective; 49 import org.onosproject.net.flowobjective.NextObjective;
48 import org.onosproject.net.flowobjective.Objective; 50 import org.onosproject.net.flowobjective.Objective;
51 +import org.onosproject.net.flowobjective.ObjectiveEvent;
49 import org.onosproject.net.group.GroupService; 52 import org.onosproject.net.group.GroupService;
50 import org.slf4j.Logger; 53 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory; 54 import org.slf4j.LoggerFactory;
...@@ -53,14 +56,14 @@ import org.slf4j.LoggerFactory; ...@@ -53,14 +56,14 @@ import org.slf4j.LoggerFactory;
53 import java.util.Collection; 56 import java.util.Collection;
54 import java.util.Collections; 57 import java.util.Collections;
55 import java.util.Map; 58 import java.util.Map;
56 -import java.util.concurrent.Future; 59 +import java.util.Set;
57 60
58 import static com.google.common.base.Preconditions.checkState; 61 import static com.google.common.base.Preconditions.checkState;
59 62
60 /** 63 /**
61 * Provides implementation of the flow objective programming service. 64 * Provides implementation of the flow objective programming service.
62 */ 65 */
63 -@Component(immediate = false) 66 +@Component(immediate = true)
64 @Service 67 @Service
65 public class FlowObjectiveManager implements FlowObjectiveService { 68 public class FlowObjectiveManager implements FlowObjectiveService {
66 69
...@@ -89,6 +92,10 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -89,6 +92,10 @@ public class FlowObjectiveManager implements FlowObjectiveService {
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected GroupService groupService; 93 protected GroupService groupService;
91 94
95 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 + protected FlowObjectiveStore flowObjectiveStore;
97 +
98 + private final FlowObjectiveStoreDelegate delegate = new InternalStoreDelegate();
92 99
93 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap(); 100 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
94 private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap(); 101 private final Map<DeviceId, Pipeliner> pipeliners = Maps.newConcurrentMap();
...@@ -101,10 +108,16 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -101,10 +108,16 @@ public class FlowObjectiveManager implements FlowObjectiveService {
101 108
102 private final Map<DeviceId, Collection<Objective>> pendingObjectives = 109 private final Map<DeviceId, Collection<Objective>> pendingObjectives =
103 Maps.newConcurrentMap(); 110 Maps.newConcurrentMap();
111 +
104 private NodeId localNode; 112 private NodeId localNode;
105 113
114 + private Map<Integer, Set<PendingNext>> pendingForwards =
115 + Maps.newConcurrentMap();
116 +
117 +
106 @Activate 118 @Activate
107 protected void activate() { 119 protected void activate() {
120 + flowObjectiveStore.setDelegate(delegate);
108 localNode = clusterService.getLocalNode().id(); 121 localNode = clusterService.getLocalNode().id();
109 mastershipService.addListener(mastershipListener); 122 mastershipService.addListener(mastershipListener);
110 deviceService.addListener(deviceListener); 123 deviceService.addListener(deviceListener);
...@@ -114,46 +127,64 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -114,46 +127,64 @@ public class FlowObjectiveManager implements FlowObjectiveService {
114 127
115 @Deactivate 128 @Deactivate
116 protected void deactivate() { 129 protected void deactivate() {
130 + flowObjectiveStore.unsetDelegate(delegate);
117 mastershipService.removeListener(mastershipListener); 131 mastershipService.removeListener(mastershipListener);
118 deviceService.removeListener(deviceListener); 132 deviceService.removeListener(deviceListener);
119 log.info("Stopped"); 133 log.info("Stopped");
120 } 134 }
121 135
122 @Override 136 @Override
123 - public Future<Boolean> filter(DeviceId deviceId, 137 + public void filter(DeviceId deviceId,
124 - Collection<FilteringObjective> filteringObjectives) { 138 + FilteringObjective filteringObjective) {
125 if (deviceService.isAvailable(deviceId)) { 139 if (deviceService.isAvailable(deviceId)) {
126 - return getDevicePipeliner(deviceId).filter(filteringObjectives); 140 + getDevicePipeliner(deviceId).filter(filteringObjective);
127 } else { 141 } else {
128 - filteringObjectives.forEach(obj -> updatePendingMap(deviceId, obj)); 142 + updatePendingMap(deviceId, filteringObjective);
129 } 143 }
130 - return Futures.immediateFuture(true); 144 +
131 } 145 }
132 146
147 + @Override
148 + public void forward(DeviceId deviceId,
149 + ForwardingObjective forwardingObjective) {
133 150
151 + if (queueObjective(deviceId, forwardingObjective)) {
152 + return;
153 + }
134 154
135 - @Override
136 - public Future<Boolean> forward(DeviceId deviceId,
137 - Collection<ForwardingObjective> forwardingObjectives) {
138 if (deviceService.isAvailable(deviceId)) { 155 if (deviceService.isAvailable(deviceId)) {
139 - return getDevicePipeliner(deviceId).forward(forwardingObjectives); 156 + getDevicePipeliner(deviceId).forward(forwardingObjective);
140 } else { 157 } else {
141 - forwardingObjectives.forEach(obj -> updatePendingMap(deviceId, obj)); 158 + updatePendingMap(deviceId, forwardingObjective);
142 } 159 }
143 - return Futures.immediateFuture(true); 160 +
144 } 161 }
145 162
146 @Override 163 @Override
147 - public Future<Boolean> next(DeviceId deviceId, 164 + public void next(DeviceId deviceId,
148 - Collection<NextObjective> nextObjectives) { 165 + NextObjective nextObjective) {
149 if (deviceService.isAvailable(deviceId)) { 166 if (deviceService.isAvailable(deviceId)) {
150 - return getDevicePipeliner(deviceId).next(nextObjectives); 167 + getDevicePipeliner(deviceId).next(nextObjective);
151 } else { 168 } else {
152 - nextObjectives.forEach(obj -> updatePendingMap(deviceId, obj)); 169 + updatePendingMap(deviceId, nextObjective);
170 + }
171 + }
172 +
173 + private boolean queueObjective(DeviceId deviceId, ForwardingObjective fwd) {
174 + if (fwd.nextId() != null &&
175 + flowObjectiveStore.getNextGroup(fwd.nextId()) == null) {
176 + log.warn("Queuing forwarding objective.");
177 + if (pendingForwards.putIfAbsent(fwd.nextId(),
178 + Sets.newHashSet(new PendingNext(deviceId, fwd))) != null) {
179 + Set<PendingNext> pending = pendingForwards.get(fwd.nextId());
180 + pending.add(new PendingNext(deviceId, fwd));
181 + }
182 + return true;
153 } 183 }
154 - return Futures.immediateFuture(true); 184 + return false;
155 } 185 }
156 186
187 +
157 private void updatePendingMap(DeviceId deviceId, Objective pending) { 188 private void updatePendingMap(DeviceId deviceId, Objective pending) {
158 if (pendingObjectives.putIfAbsent(deviceId, Lists.newArrayList(pending)) != null) { 189 if (pendingObjectives.putIfAbsent(deviceId, Lists.newArrayList(pending)) != null) {
159 Collection<Objective> objectives = pendingObjectives.get(deviceId); 190 Collection<Objective> objectives = pendingObjectives.get(deviceId);
...@@ -169,6 +200,33 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -169,6 +200,33 @@ public class FlowObjectiveManager implements FlowObjectiveService {
169 return pipeliner; 200 return pipeliner;
170 } 201 }
171 202
203 + private void setupPipelineHandler(DeviceId deviceId) {
204 + if (localNode.equals(mastershipService.getMasterFor(deviceId))) {
205 + // Attempt to lookup the handler in the cache
206 + DriverHandler handler = driverHandlers.get(deviceId);
207 + if (handler == null) {
208 + try {
209 + // Otherwise create it and if it has pipeline behaviour, cache it
210 + handler = driverService.createHandler(deviceId);
211 + if (!handler.driver().hasBehaviour(Pipeliner.class)) {
212 + log.warn("Pipeline behaviour not supported for device {}",
213 + deviceId);
214 + return;
215 + }
216 + } catch (ItemNotFoundException e) {
217 + log.warn("No applicable driver for device {}", deviceId);
218 + return;
219 + }
220 + driverHandlers.put(deviceId, handler);
221 + }
222 +
223 + // Always (re)initialize the pipeline behaviour
224 + Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
225 + pipeliner.init(deviceId, context);
226 + pipeliners.putIfAbsent(deviceId, pipeliner);
227 + log.info("Driver {} bound to device {}", handler.driver().name(), deviceId);
228 + }
229 + }
172 230
173 // Triggers driver setup when the local node becomes a device master. 231 // Triggers driver setup when the local node becomes a device master.
174 private class InnerMastershipListener implements MastershipListener { 232 private class InnerMastershipListener implements MastershipListener {
...@@ -221,52 +279,70 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -221,52 +279,70 @@ public class FlowObjectiveManager implements FlowObjectiveService {
221 pendingObjectives.getOrDefault(deviceId, 279 pendingObjectives.getOrDefault(deviceId,
222 Collections.emptySet()).forEach(obj -> { 280 Collections.emptySet()).forEach(obj -> {
223 if (obj instanceof NextObjective) { 281 if (obj instanceof NextObjective) {
224 - getDevicePipeliner(deviceId) 282 + next(deviceId, (NextObjective) obj);
225 - .next(Collections.singletonList((NextObjective) obj));
226 } else if (obj instanceof ForwardingObjective) { 283 } else if (obj instanceof ForwardingObjective) {
227 - getDevicePipeliner(deviceId) 284 + forward(deviceId, (ForwardingObjective) obj);
228 - .forward(Collections.singletonList((ForwardingObjective) obj));
229 } else { 285 } else {
230 getDevicePipeliner(deviceId) 286 getDevicePipeliner(deviceId)
231 - .filter(Collections.singletonList((FilteringObjective) obj)); 287 + .filter((FilteringObjective) obj);
232 } 288 }
233 }); 289 });
234 } 290 }
235 } 291 }
236 292
237 - private void setupPipelineHandler(DeviceId deviceId) {
238 - if (localNode.equals(mastershipService.getMasterFor(deviceId))) {
239 - // Attempt to lookup the handler in the cache
240 - DriverHandler handler = driverHandlers.get(deviceId);
241 - if (handler == null) {
242 - try {
243 - // Otherwise create it and if it has pipeline behaviour, cache it
244 - handler = driverService.createHandler(deviceId);
245 - if (!handler.driver().hasBehaviour(Pipeliner.class)) {
246 - log.warn("Pipeline behaviour not supported for device {}",
247 - deviceId);
248 - return;
249 - }
250 - } catch (ItemNotFoundException e) {
251 - log.warn("No applicable driver for device {}", deviceId);
252 - return;
253 - }
254 - driverHandlers.put(deviceId, handler);
255 - }
256 -
257 - // Always (re)initialize the pipeline behaviour
258 - Pipeliner pipeliner = handler.behaviour(Pipeliner.class);
259 - pipeliner.init(deviceId, context);
260 - pipeliners.putIfAbsent(deviceId, pipeliner);
261 - log.info("Driver {} bound to device {}", handler.driver().name(), deviceId);
262 - }
263 - }
264 -
265 // Processing context for initializing pipeline driver behaviours. 293 // Processing context for initializing pipeline driver behaviours.
266 private class InnerPipelineContext implements PipelinerContext { 294 private class InnerPipelineContext implements PipelinerContext {
267 @Override 295 @Override
268 public ServiceDirectory directory() { 296 public ServiceDirectory directory() {
269 return serviceDirectory; 297 return serviceDirectory;
270 } 298 }
299 +
300 + @Override
301 + public FlowObjectiveStore store() {
302 + return flowObjectiveStore;
303 + }
304 +
305 +
306 + }
307 +
308 + private class InternalStoreDelegate implements FlowObjectiveStoreDelegate {
309 + @Override
310 + public void notify(ObjectiveEvent event) {
311 + Set<PendingNext> pending = pendingForwards.remove(event.subject());
312 +
313 + if (pending == null) {
314 + return;
315 + }
316 +
317 + log.info("Processing pending objectives {}", pending.size());
318 +
319 + pending.forEach(p -> getDevicePipeliner(p.deviceId())
320 + .forward(p.forwardingObjective()));
321 +
322 + }
323 + }
324 +
325 + /**
326 + * Data class used to hold a pending forwarding objective that could not
327 + * be processed because the associated next object was not present.
328 + */
329 + private class PendingNext {
330 + private final DeviceId deviceId;
331 + private final ForwardingObjective fwd;
332 +
333 + public PendingNext(DeviceId deviceId, ForwardingObjective fwd) {
334 + this.deviceId = deviceId;
335 + this.fwd = fwd;
336 + }
337 +
338 + public DeviceId deviceId() {
339 + return deviceId;
340 + }
341 +
342 + public ForwardingObjective forwardingObjective() {
343 + return fwd;
344 + }
345 +
346 +
271 } 347 }
272 } 348 }
......
1 +/*
2 + * Copyright 2015 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 +package org.onosproject.store.flowobjective.impl;
17 +
18 +import org.apache.felix.scr.annotations.Activate;
19 +import org.apache.felix.scr.annotations.Component;
20 +import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Reference;
22 +import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.apache.felix.scr.annotations.Service;
24 +import org.onlab.util.KryoNamespace;
25 +import org.onosproject.net.behaviour.DefaultNextGroup;
26 +import org.onosproject.net.behaviour.NextGroup;
27 +import org.onosproject.net.flowobjective.FlowObjectiveStore;
28 +import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
29 +import org.onosproject.net.flowobjective.ObjectiveEvent;
30 +import org.onosproject.store.AbstractStore;
31 +import org.onosproject.store.service.ConsistentMap;
32 +import org.onosproject.store.service.Serializer;
33 +import org.onosproject.store.service.StorageService;
34 +import org.onosproject.store.service.Versioned;
35 +import org.slf4j.Logger;
36 +
37 +import static org.slf4j.LoggerFactory.getLogger;
38 +
39 +/**
40 + * Manages the inventory of created next groups.
41 + */
42 +@Component(immediate = true, enabled = true)
43 +@Service
44 +public class DistributedFlowObjectiveStore
45 + extends AbstractStore<ObjectiveEvent, FlowObjectiveStoreDelegate>
46 + implements FlowObjectiveStore {
47 +
48 + private final Logger log = getLogger(getClass());
49 +
50 + private ConsistentMap<Integer, byte[]> nextGroups;
51 +
52 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 + protected StorageService storageService;
54 +
55 + @Activate
56 + public void activate() {
57 + nextGroups = storageService.<Integer, byte[]>consistentMapBuilder()
58 + .withName("flowobjective-groups")
59 + .withSerializer(Serializer.using(
60 + new KryoNamespace.Builder()
61 + .register(byte[].class)
62 + .build()))
63 + .build();
64 +
65 + log.info("Started");
66 + }
67 +
68 +
69 + @Deactivate
70 + public void deactivate() {
71 + log.info("Stopped");
72 + }
73 +
74 +
75 + @Override
76 + public void putNextGroup(Integer nextId, NextGroup group) {
77 + nextGroups.putIfAbsent(nextId, group.data());
78 + notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.ADD, nextId));
79 + }
80 +
81 + @Override
82 + public NextGroup getNextGroup(Integer nextId) {
83 + Versioned<byte[]> versionGroup = nextGroups.get(nextId);
84 + if (versionGroup != null) {
85 + return new DefaultNextGroup(versionGroup.value());
86 + }
87 + return null;
88 + }
89 +}
...@@ -167,10 +167,13 @@ public class DistributedPacketStore ...@@ -167,10 +167,13 @@ public class DistributedPacketStore
167 public PacketRequestTracker() { 167 public PacketRequestTracker() {
168 requests = storageService.<PacketRequest, Boolean>consistentMapBuilder() 168 requests = storageService.<PacketRequest, Boolean>consistentMapBuilder()
169 .withName("packet-requests") 169 .withName("packet-requests")
170 + .withSerializer(Serializer.using(
171 + new KryoNamespace.Builder().register(KryoNamespaces.API).build()))
170 .withSerializer(new Serializer() { 172 .withSerializer(new Serializer() {
171 KryoNamespace kryo = new KryoNamespace.Builder() 173 KryoNamespace kryo = new KryoNamespace.Builder()
172 .register(KryoNamespaces.API) 174 .register(KryoNamespaces.API)
173 .build(); 175 .build();
176 +
174 @Override 177 @Override
175 public <T> byte[] encode(T object) { 178 public <T> byte[] encode(T object) {
176 return kryo.serialize(object); 179 return kryo.serialize(object);
......
...@@ -44,6 +44,12 @@ ...@@ -44,6 +44,12 @@
44 </dependency> 44 </dependency>
45 45
46 <dependency> 46 <dependency>
47 + <groupId>org.onosproject</groupId>
48 + <artifactId>onos-core-serializers</artifactId>
49 + <version>1.2.0-SNAPSHOT</version>
50 + </dependency>
51 +
52 + <dependency>
47 <groupId>org.easymock</groupId> 53 <groupId>org.easymock</groupId>
48 <artifactId>easymock</artifactId> 54 <artifactId>easymock</artifactId>
49 <scope>test</scope> 55 <scope>test</scope>
......
...@@ -31,11 +31,9 @@ import org.onosproject.net.flow.TrafficSelector; ...@@ -31,11 +31,9 @@ import org.onosproject.net.flow.TrafficSelector;
31 import org.onosproject.net.flowobjective.FilteringObjective; 31 import org.onosproject.net.flowobjective.FilteringObjective;
32 import org.onosproject.net.flowobjective.ForwardingObjective; 32 import org.onosproject.net.flowobjective.ForwardingObjective;
33 import org.onosproject.net.flowobjective.NextObjective; 33 import org.onosproject.net.flowobjective.NextObjective;
34 +import org.onosproject.net.flowobjective.ObjectiveError;
34 import org.slf4j.Logger; 35 import org.slf4j.Logger;
35 36
36 -import java.util.Collection;
37 -import java.util.concurrent.Future;
38 -
39 import static org.slf4j.LoggerFactory.getLogger; 37 import static org.slf4j.LoggerFactory.getLogger;
40 38
41 /** 39 /**
...@@ -58,59 +56,62 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme ...@@ -58,59 +56,62 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme
58 } 56 }
59 57
60 @Override 58 @Override
61 - public Future<Boolean> filter(Collection<FilteringObjective> filters) { 59 + public void filter(FilteringObjective filter) {
62 throw new UnsupportedOperationException("Single table does not filter."); 60 throw new UnsupportedOperationException("Single table does not filter.");
63 } 61 }
64 62
65 @Override 63 @Override
66 - public Future<Boolean> forward(Collection<ForwardingObjective> forwardings) { 64 + public void forward(ForwardingObjective fwd) {
67 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); 65 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
68 - forwardings.forEach(fwd -> {
69 - if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
70 - throw new UnsupportedOperationException(
71 - "Only VERSATILE is supported.");
72 - }
73 66
74 - TrafficSelector selector = fwd.selector(); 67 + if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
68 + throw new UnsupportedOperationException(
69 + "Only VERSATILE is supported.");
70 + }
75 71
76 - FlowRule rule = new DefaultFlowRule(deviceId, selector, 72 + TrafficSelector selector = fwd.selector();
77 - fwd.treatment(),
78 - fwd.priority(), fwd.appId(),
79 - new DefaultGroupId(fwd.id()),
80 - fwd.timeout(), fwd.permanent());
81 73
82 - switch (fwd.op()) { 74 + FlowRule rule = new DefaultFlowRule(deviceId, selector,
75 + fwd.treatment(),
76 + fwd.priority(), fwd.appId(),
77 + new DefaultGroupId(fwd.id()),
78 + fwd.timeout(), fwd.permanent());
83 79
84 - case ADD: 80 + switch (fwd.op()) {
85 - flowBuilder.add(rule); 81 +
86 - break; 82 + case ADD:
87 - case REMOVE: 83 + flowBuilder.add(rule);
88 - flowBuilder.remove(rule); 84 + break;
89 - break; 85 + case REMOVE:
90 - default: 86 + flowBuilder.remove(rule);
91 - log.warn("Unknown operation {}", fwd.op()); 87 + break;
92 - } 88 + default:
89 + log.warn("Unknown operation {}", fwd.op());
90 + }
93 91
94 - });
95 92
96 SettableFuture<Boolean> future = SettableFuture.create(); 93 SettableFuture<Boolean> future = SettableFuture.create();
97 94
98 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { 95 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
99 @Override 96 @Override
100 public void onSuccess(FlowRuleOperations ops) { 97 public void onSuccess(FlowRuleOperations ops) {
101 - future.set(true); 98 + if (fwd.context().isPresent()) {
99 + fwd.context().get().onSuccess(fwd);
100 + }
102 } 101 }
103 102
104 @Override 103 @Override
105 public void onError(FlowRuleOperations ops) { 104 public void onError(FlowRuleOperations ops) {
106 - future.set(false); 105 + if (fwd.context().isPresent()) {
106 + fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
107 + }
107 } 108 }
108 })); 109 }));
109 - return future; 110 +
110 } 111 }
111 112
112 @Override 113 @Override
113 - public Future<Boolean> next(Collection<NextObjective> nextObjectives) { 114 + public void next(NextObjective nextObjective) {
114 throw new UnsupportedOperationException("Single table does not next hop."); 115 throw new UnsupportedOperationException("Single table does not next hop.");
115 } 116 }
116 117
......
...@@ -15,15 +15,19 @@ ...@@ -15,15 +15,19 @@
15 */ 15 */
16 package org.onosproject.driver.pipeline; 16 package org.onosproject.driver.pipeline;
17 17
18 -import com.google.common.collect.Sets; 18 +import com.google.common.cache.Cache;
19 -import com.google.common.util.concurrent.SettableFuture; 19 +import com.google.common.cache.CacheBuilder;
20 +import com.google.common.cache.RemovalCause;
21 +import com.google.common.cache.RemovalNotification;
20 import org.onlab.osgi.ServiceDirectory; 22 import org.onlab.osgi.ServiceDirectory;
21 import org.onlab.packet.Ethernet; 23 import org.onlab.packet.Ethernet;
22 import org.onlab.packet.MacAddress; 24 import org.onlab.packet.MacAddress;
23 import org.onlab.packet.VlanId; 25 import org.onlab.packet.VlanId;
26 +import org.onlab.util.KryoNamespace;
24 import org.onosproject.core.ApplicationId; 27 import org.onosproject.core.ApplicationId;
25 import org.onosproject.core.CoreService; 28 import org.onosproject.core.CoreService;
26 import org.onosproject.net.DeviceId; 29 import org.onosproject.net.DeviceId;
30 +import org.onosproject.net.behaviour.NextGroup;
27 import org.onosproject.net.behaviour.Pipeliner; 31 import org.onosproject.net.behaviour.Pipeliner;
28 import org.onosproject.net.behaviour.PipelinerContext; 32 import org.onosproject.net.behaviour.PipelinerContext;
29 import org.onosproject.net.driver.AbstractHandlerBehaviour; 33 import org.onosproject.net.driver.AbstractHandlerBehaviour;
...@@ -39,18 +43,37 @@ import org.onosproject.net.flow.TrafficTreatment; ...@@ -39,18 +43,37 @@ import org.onosproject.net.flow.TrafficTreatment;
39 import org.onosproject.net.flow.criteria.Criteria; 43 import org.onosproject.net.flow.criteria.Criteria;
40 import org.onosproject.net.flow.criteria.Criterion; 44 import org.onosproject.net.flow.criteria.Criterion;
41 import org.onosproject.net.flowobjective.FilteringObjective; 45 import org.onosproject.net.flowobjective.FilteringObjective;
46 +import org.onosproject.net.flowobjective.FlowObjectiveStore;
42 import org.onosproject.net.flowobjective.ForwardingObjective; 47 import org.onosproject.net.flowobjective.ForwardingObjective;
43 import org.onosproject.net.flowobjective.NextObjective; 48 import org.onosproject.net.flowobjective.NextObjective;
44 import org.onosproject.net.flowobjective.Objective; 49 import org.onosproject.net.flowobjective.Objective;
50 +import org.onosproject.net.flowobjective.ObjectiveError;
51 +import org.onosproject.net.group.DefaultGroupBucket;
52 +import org.onosproject.net.group.DefaultGroupDescription;
53 +import org.onosproject.net.group.DefaultGroupKey;
54 +import org.onosproject.net.group.Group;
55 +import org.onosproject.net.group.GroupBucket;
56 +import org.onosproject.net.group.GroupBuckets;
57 +import org.onosproject.net.group.GroupDescription;
58 +import org.onosproject.net.group.GroupEvent;
59 +import org.onosproject.net.group.GroupKey;
60 +import org.onosproject.net.group.GroupListener;
61 +import org.onosproject.net.group.GroupService;
45 import org.slf4j.Logger; 62 import org.slf4j.Logger;
46 63
47 import java.util.Collection; 64 import java.util.Collection;
48 -import java.util.concurrent.Future; 65 +import java.util.Collections;
49 - 66 +import java.util.Set;
67 +import java.util.concurrent.Executors;
68 +import java.util.concurrent.ScheduledExecutorService;
69 +import java.util.concurrent.TimeUnit;
70 +import java.util.stream.Collectors;
71 +
72 +import static org.onlab.util.Tools.groupedThreads;
50 import static org.slf4j.LoggerFactory.getLogger; 73 import static org.slf4j.LoggerFactory.getLogger;
51 74
52 /** 75 /**
53 - * Corsa pipeline handler. 76 + * OpenvSwitch emulation of the Corsa pipeline handler.
54 */ 77 */
55 public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner { 78 public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
56 79
...@@ -63,17 +86,45 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli ...@@ -63,17 +86,45 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
63 private ServiceDirectory serviceDirectory; 86 private ServiceDirectory serviceDirectory;
64 private FlowRuleService flowRuleService; 87 private FlowRuleService flowRuleService;
65 private CoreService coreService; 88 private CoreService coreService;
89 + private GroupService groupService;
90 + private FlowObjectiveStore flowObjectiveStore;
66 private DeviceId deviceId; 91 private DeviceId deviceId;
67 private ApplicationId appId; 92 private ApplicationId appId;
68 93
94 + private KryoNamespace appKryo = new KryoNamespace.Builder()
95 + .register(GroupKey.class)
96 + .register(DefaultGroupKey.class)
97 + .register(CorsaGroup.class)
98 + .register(byte[].class)
99 + .build();
100 +
101 + private Cache<GroupKey, NextObjective> pendingGroups;
102 +
103 + private ScheduledExecutorService groupChecker =
104 + Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
105 + "ovs-corsa-%d"));
106 +
69 @Override 107 @Override
70 public void init(DeviceId deviceId, PipelinerContext context) { 108 public void init(DeviceId deviceId, PipelinerContext context) {
71 this.serviceDirectory = context.directory(); 109 this.serviceDirectory = context.directory();
72 this.deviceId = deviceId; 110 this.deviceId = deviceId;
73 111
112 + pendingGroups = CacheBuilder.newBuilder()
113 + .expireAfterWrite(20, TimeUnit.SECONDS)
114 + .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
115 + if (notification.getCause() == RemovalCause.EXPIRED) {
116 + fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
117 + }
118 + }).build();
119 +
120 + groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
74 121
75 coreService = serviceDirectory.get(CoreService.class); 122 coreService = serviceDirectory.get(CoreService.class);
76 flowRuleService = serviceDirectory.get(FlowRuleService.class); 123 flowRuleService = serviceDirectory.get(FlowRuleService.class);
124 + groupService = serviceDirectory.get(GroupService.class);
125 + flowObjectiveStore = context.store();
126 +
127 + groupService.addListener(new InnerGroupListener());
77 128
78 appId = coreService.registerApplication( 129 appId = coreService.registerApplication(
79 "org.onosproject.driver.OVSCorsaPipeline"); 130 "org.onosproject.driver.OVSCorsaPipeline");
...@@ -82,33 +133,159 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli ...@@ -82,33 +133,159 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
82 } 133 }
83 134
84 @Override 135 @Override
85 - public Future<Boolean> filter(Collection<FilteringObjective> filteringObjectives) { 136 + public void filter(FilteringObjective filteringObjective) {
86 - Collection<Future<Boolean>> results = Sets.newHashSet(); 137 + if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
87 - filteringObjectives.stream() 138 + processFilter(filteringObjective,
88 - .filter(obj -> obj.type() == FilteringObjective.Type.PERMIT) 139 + filteringObjective.op() == Objective.Operation.ADD,
89 - .forEach(filtobj -> results.add(processFilter(filtobj, 140 + filteringObjective.appId());
90 - filtobj.op() == Objective.Operation.ADD, 141 + } else {
91 - filtobj.appId() 142 + fail(filteringObjective, ObjectiveError.UNSUPPORTED);
92 - ))); 143 + }
93 - 144 + }
94 - //TODO: return something more helpful/sensible in the future (no pun intended) 145 +
95 - return results.iterator().next(); 146 + @Override
147 + public void forward(ForwardingObjective fwd) {
148 + Collection<FlowRule> rules;
149 + FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
150 +
151 + rules = processForward(fwd);
152 + switch (fwd.op()) {
153 + case ADD:
154 + rules.stream()
155 + .filter(rule -> rule != null)
156 + .forEach(flowBuilder::add);
157 + break;
158 + case REMOVE:
159 + rules.stream()
160 + .filter(rule -> rule != null)
161 + .forEach(flowBuilder::remove);
162 + break;
163 + default:
164 + fail(fwd, ObjectiveError.UNKNOWN);
165 + log.warn("Unknown forwarding type {}", fwd.op());
166 + }
167 +
168 +
169 + flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
170 + @Override
171 + public void onSuccess(FlowRuleOperations ops) {
172 + pass(fwd);
173 + }
174 +
175 + @Override
176 + public void onError(FlowRuleOperations ops) {
177 + fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
178 + }
179 + }));
180 +
181 + }
182 +
183 + @Override
184 + public void next(NextObjective nextObjective) {
185 + switch (nextObjective.type()) {
186 + case SIMPLE:
187 + Collection<TrafficTreatment> treatments = nextObjective.next();
188 + if (treatments.size() == 1) {
189 + TrafficTreatment treatment = treatments.iterator().next();
190 + GroupBucket bucket =
191 + DefaultGroupBucket.createIndirectGroupBucket(treatment);
192 + final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
193 + GroupDescription groupDescription
194 + = new DefaultGroupDescription(deviceId,
195 + GroupDescription.Type.INDIRECT,
196 + new GroupBuckets(Collections
197 + .singletonList(bucket)),
198 + key,
199 + nextObjective.appId());
200 + groupService.addGroup(groupDescription);
201 + pendingGroups.put(key, nextObjective);
202 + }
203 + break;
204 + case HASHED:
205 + case BROADCAST:
206 + case FAILOVER:
207 + fail(nextObjective, ObjectiveError.UNSUPPORTED);
208 + log.warn("Unsupported next objective type {}", nextObjective.type());
209 + break;
210 + default:
211 + fail(nextObjective, ObjectiveError.UNKNOWN);
212 + log.warn("Unknown next objective type {}", nextObjective.type());
213 + }
214 +
215 + }
216 +
217 + private Collection<FlowRule> processForward(ForwardingObjective fwd) {
218 + switch (fwd.flag()) {
219 + case SPECIFIC:
220 + return processSpecific(fwd);
221 + case VERSATILE:
222 + return processVersatile(fwd);
223 + default:
224 + fail(fwd, ObjectiveError.UNKNOWN);
225 + log.warn("Unknown forwarding flag {}", fwd.flag());
226 + }
227 + return Collections.emptySet();
228 + }
229 +
230 + private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
231 + fail(fwd, ObjectiveError.UNSUPPORTED);
232 + return Collections.emptySet();
233 + }
234 +
235 + private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
236 + log.warn("Processing specific");
237 + TrafficSelector selector = fwd.selector();
238 + Criteria.EthTypeCriterion ethType =
239 + (Criteria.EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
240 + if (ethType == null || ethType.ethType() != Ethernet.TYPE_IPV4) {
241 + fail(fwd, ObjectiveError.UNSUPPORTED);
242 + return Collections.emptySet();
243 + }
244 +
245 + TrafficSelector filteredSelector =
246 + DefaultTrafficSelector.builder()
247 + .matchEthType(Ethernet.TYPE_IPV4)
248 + .matchIPDst(
249 + ((Criteria.IPCriterion)
250 + selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
251 + .build();
252 +
253 + NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
254 +
255 + GroupKey key = appKryo.deserialize(next.data());
256 +
257 + Group group = groupService.getGroup(deviceId, key);
258 +
259 + if (group == null) {
260 + log.warn("The group left!");
261 + fail(fwd, ObjectiveError.GROUPMISSING);
262 + return Collections.emptySet();
263 + }
264 +
265 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
266 + .group(group.id())
267 + .build();
268 +
269 + return Collections.singletonList(
270 + new DefaultFlowRule(deviceId, filteredSelector, treatment,
271 + fwd.priority(), fwd.appId(), 0, fwd.permanent(),
272 + FlowRule.Type.IP));
96 273
97 } 274 }
98 275
99 - private Future<Boolean> processFilter(FilteringObjective filt, boolean install, 276 + private void processFilter(FilteringObjective filt, boolean install,
100 ApplicationId applicationId) { 277 ApplicationId applicationId) {
101 - SettableFuture<Boolean> result = SettableFuture.create();
102 // This driver only processes filtering criteria defined with switch 278 // This driver only processes filtering criteria defined with switch
103 // ports as the key 279 // ports as the key
104 - Criteria.PortCriterion p = null; 280 + Criteria.PortCriterion p;
105 if (!filt.key().equals(Criteria.dummy()) && 281 if (!filt.key().equals(Criteria.dummy()) &&
106 filt.key().type() == Criterion.Type.IN_PORT) { 282 filt.key().type() == Criterion.Type.IN_PORT) {
107 p = (Criteria.PortCriterion) filt.key(); 283 p = (Criteria.PortCriterion) filt.key();
108 } else { 284 } else {
109 log.warn("No key defined in filtering objective from app: {}. Not" 285 log.warn("No key defined in filtering objective from app: {}. Not"
110 + "processing filtering objective", applicationId); 286 + "processing filtering objective", applicationId);
111 - return null; 287 + fail(filt, ObjectiveError.UNKNOWN);
288 + return;
112 } 289 }
113 // convert filtering conditions for switch-intfs into flowrules 290 // convert filtering conditions for switch-intfs into flowrules
114 FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); 291 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
...@@ -154,45 +331,45 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli ...@@ -154,45 +331,45 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
154 } else { 331 } else {
155 log.warn("Driver does not currently process filtering condition" 332 log.warn("Driver does not currently process filtering condition"
156 + " of type: {}", c.type()); 333 + " of type: {}", c.type());
334 + fail(filt, ObjectiveError.UNSUPPORTED);
157 } 335 }
158 } 336 }
159 // apply filtering flow rules 337 // apply filtering flow rules
160 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { 338 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
161 @Override 339 @Override
162 public void onSuccess(FlowRuleOperations ops) { 340 public void onSuccess(FlowRuleOperations ops) {
163 - result.set(true); 341 + pass(filt);
164 log.info("Provisioned default table for bgp router"); 342 log.info("Provisioned default table for bgp router");
165 } 343 }
166 344
167 @Override 345 @Override
168 public void onError(FlowRuleOperations ops) { 346 public void onError(FlowRuleOperations ops) {
169 - result.set(false); 347 + fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
170 log.info("Failed to provision default table for bgp router"); 348 log.info("Failed to provision default table for bgp router");
171 } 349 }
172 })); 350 }));
173 -
174 - return result;
175 } 351 }
176 352
177 - @Override 353 + private void pass(Objective obj) {
178 - public Future<Boolean> forward(Collection<ForwardingObjective> forwardObjectives) { 354 + if (obj.context().isPresent()) {
179 - return null; 355 + obj.context().get().onSuccess(obj);
356 + }
180 } 357 }
181 358
182 - @Override 359 + private void fail(Objective obj, ObjectiveError error) {
183 - public Future<Boolean> next(Collection<NextObjective> nextObjectives) { 360 + if (obj.context().isPresent()) {
184 - return null; 361 + obj.context().get().onError(obj, error);
362 + }
185 } 363 }
186 364
187 private void pushDefaultRules() { 365 private void pushDefaultRules() {
188 - boolean install = true; 366 + processTableZero(true);
189 - processTableZero(install); 367 + processTableOne(true);
190 - processTableOne(install); 368 + processTableTwo(true);
191 - processTableTwo(install); 369 + processTableFour(true);
192 - processTableFour(install); 370 + processTableFive(true);
193 - processTableFive(install); 371 + processTableSix(true);
194 - processTableSix(install); 372 + processTableNine(true);
195 - processTableNine(install);
196 } 373 }
197 374
198 private void processTableZero(boolean install) { 375 private void processTableZero(boolean install) {
...@@ -447,4 +624,59 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli ...@@ -447,4 +624,59 @@ public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeli
447 })); 624 }));
448 } 625 }
449 626
627 + private class InnerGroupListener implements GroupListener {
628 + @Override
629 + public void event(GroupEvent event) {
630 + if (event.type() == GroupEvent.Type.GROUP_ADDED) {
631 + GroupKey key = event.subject().appCookie();
632 +
633 + NextObjective obj = pendingGroups.getIfPresent(key);
634 + if (obj != null) {
635 + flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
636 + pass(obj);
637 + pendingGroups.invalidate(key);
638 + }
639 + }
640 + }
641 + }
642 +
643 +
644 + private class GroupChecker implements Runnable {
645 +
646 + @Override
647 + public void run() {
648 + Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
649 + .filter(key -> groupService.getGroup(deviceId, key) != null)
650 + .collect(Collectors.toSet());
651 +
652 + keys.stream().forEach(key -> {
653 + NextObjective obj = pendingGroups.getIfPresent(key);
654 + if (obj == null) {
655 + return;
656 + }
657 + pass(obj);
658 + pendingGroups.invalidate(key);
659 + flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
660 + });
661 + }
662 + }
663 +
664 + private class CorsaGroup implements NextGroup {
665 +
666 + private final GroupKey key;
667 +
668 + public CorsaGroup(GroupKey key) {
669 + this.key = key;
670 + }
671 +
672 + public GroupKey key() {
673 + return key;
674 + }
675 +
676 + @Override
677 + public byte[] data() {
678 + return appKryo.serialize(key);
679 + }
680 +
681 + }
450 } 682 }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
19 <behaviour api="org.onosproject.net.behaviour.Pipeliner" 19 <behaviour api="org.onosproject.net.behaviour.Pipeliner"
20 impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/> 20 impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
21 </driver> 21 </driver>
22 - <driver name="ovs-corsa" manufacturer="Nicira, Inc." hwVersion="Open vSwitch" swVersion="2.3.0"> 22 + <driver name="ovs-corsa" manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
23 <behaviour api="org.onosproject.net.behaviour.Pipeliner" 23 <behaviour api="org.onosproject.net.behaviour.Pipeliner"
24 impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/> 24 impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
25 </driver> 25 </driver>
......
...@@ -195,7 +195,6 @@ public class FlowModBuilderVer13 extends FlowModBuilder { ...@@ -195,7 +195,6 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
195 for (Instruction i : treatments) { 195 for (Instruction i : treatments) {
196 switch (i.type()) { 196 switch (i.type()) {
197 case DROP: 197 case DROP:
198 - log.warn("Saw drop action; assigning drop action");
199 return new LinkedList<>(); 198 return new LinkedList<>();
200 case L0MODIFICATION: 199 case L0MODIFICATION:
201 actions.add(buildL0Modification(i)); 200 actions.add(buildL0Modification(i));
......