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 665 additions and 69 deletions
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.behaviour;
/**
* Default implementation of a next group.
*/
public class DefaultNextGroup implements NextGroup {
private final byte[] data;
public DefaultNextGroup(byte[] data) {
this.data = data;
}
@Override
public byte[] data() {
return data;
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.behaviour;
/**
* Opaque data type for carrying group-like information.
* Only relevant to a pipeliner driver.
*/
public interface NextGroup {
/**
* Serialized form of the next group.
* @return a byte array.
*/
byte[] data();
}
......@@ -21,9 +21,6 @@ import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import java.util.Collection;
import java.util.concurrent.Future;
/**
* Behaviour for handling various pipelines.
*/
......@@ -40,24 +37,21 @@ public interface Pipeliner extends HandlerBehaviour {
/**
* Installs the filtering rules onto the device.
*
* @param filterObjectives the collection of filters
* @return a future indicating the success of the operation
* @param filterObjective a filtering objective
*/
Future<Boolean> filter(Collection<FilteringObjective> filterObjectives);
void filter(FilteringObjective filterObjective);
/**
* Installs the forwarding rules onto the device.
*
* @param forwardObjectives the collection of forwarding objectives
* @return a future indicating the success of the operation
* @param forwardObjective a forwarding objective
*/
Future<Boolean> forward(Collection<ForwardingObjective> forwardObjectives);
void forward(ForwardingObjective forwardObjective);
/**
* Installs the next hop elements into the device.
*
* @param nextObjectives the collection of next objectives
* @return a future indicating the success of the operation
* @param nextObjective a next objectives
*/
Future<Boolean> next(Collection<NextObjective> nextObjectives);
void next(NextObjective nextObjective);
}
......
......@@ -16,6 +16,7 @@
package org.onosproject.net.behaviour;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
/**
* Processing context and supporting services for the pipeline behaviour.
......@@ -30,5 +31,11 @@ public interface PipelinerContext {
*/
ServiceDirectory directory();
/**
* Returns the Objective Store where data can be stored and retrieved.
* @return the flow objective store
*/
FlowObjectiveStore store();
// TODO: add means to store and access shared state
}
......
......@@ -23,6 +23,7 @@ import org.onosproject.net.flow.criteria.Criterion;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -42,6 +43,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
private final List<Criterion> conditions;
private final int id;
private final Operation op;
private final Optional<ObjectiveContext> context;
private DefaultFilteringObjective(Type type, boolean permanent, int timeout,
ApplicationId appId, int priority, Criterion key,
......@@ -54,6 +56,25 @@ public final class DefaultFilteringObjective implements FilteringObjective {
this.priority = priority;
this.conditions = conditions;
this.op = op;
this.context = Optional.empty();
this.id = Objects.hash(type, key, conditions, permanent,
timeout, appId, priority);
}
public DefaultFilteringObjective(Type type, boolean permanent, int timeout,
ApplicationId appId, int priority, Criterion key,
List<Criterion> conditions,
ObjectiveContext context, Operation op) {
this.key = key;
this.type = type;
this.permanent = permanent;
this.timeout = timeout;
this.appId = appId;
this.priority = priority;
this.conditions = conditions;
this.op = op;
this.context = Optional.ofNullable(context);
this.id = Objects.hash(type, key, conditions, permanent,
timeout, appId, priority);
......@@ -104,6 +125,11 @@ public final class DefaultFilteringObjective implements FilteringObjective {
return op;
}
@Override
public Optional<ObjectiveContext> context() {
return context;
}
/**
* Returns a new builder.
*
......@@ -201,6 +227,31 @@ public final class DefaultFilteringObjective implements FilteringObjective {
}
@Override
public FilteringObjective add(ObjectiveContext context) {
List<Criterion> conditions = listBuilder.build();
checkNotNull(type, "Must have a type.");
checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
checkNotNull(appId, "Must supply an application id");
return new DefaultFilteringObjective(type, permanent, timeout,
appId, priority, key, conditions,
context, Operation.ADD);
}
@Override
public FilteringObjective remove(ObjectiveContext context) {
List<Criterion> conditions = listBuilder.build();
checkNotNull(type, "Must have a type.");
checkArgument(!conditions.isEmpty(), "Must have at least one condition.");
checkNotNull(appId, "Must supply an application id");
return new DefaultFilteringObjective(type, permanent, timeout,
appId, priority, key, conditions,
context, Operation.REMOVE);
}
}
......
......@@ -20,6 +20,7 @@ import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -38,6 +39,7 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
private final int nextId;
private final TrafficTreatment treatment;
private final Operation op;
private final Optional<ObjectiveContext> context;
private final int id;
......@@ -55,6 +57,29 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
this.nextId = nextId;
this.treatment = treatment;
this.op = op;
this.context = Optional.empty();
this.id = Objects.hash(selector, flag, permanent,
timeout, appId, priority, nextId,
treatment, op);
}
private DefaultForwardingObjective(TrafficSelector selector,
Flag flag, boolean permanent,
int timeout, ApplicationId appId,
int priority, int nextId,
TrafficTreatment treatment,
ObjectiveContext context, Operation op) {
this.selector = selector;
this.flag = flag;
this.permanent = permanent;
this.timeout = timeout;
this.appId = appId;
this.priority = priority;
this.nextId = nextId;
this.treatment = treatment;
this.op = op;
this.context = Optional.ofNullable(context);
this.id = Objects.hash(selector, flag, permanent,
timeout, appId, priority, nextId,
......@@ -113,6 +138,11 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
return op;
}
@Override
public Optional<ObjectiveContext> context() {
return context;
}
/**
* Returns a new builder.
*
......@@ -186,7 +216,7 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
public ForwardingObjective add() {
checkNotNull(selector, "Must have a selector");
checkNotNull(flag, "A flag must be set");
checkArgument(nextId != null && treatment != null, "Must supply at " +
checkArgument(nextId != null || treatment != null, "Must supply at " +
"least a treatment and/or a nextId");
checkNotNull(appId, "Must supply an application id");
return new DefaultForwardingObjective(selector, flag, permanent,
......@@ -198,12 +228,38 @@ public final class DefaultForwardingObjective implements ForwardingObjective {
public ForwardingObjective remove() {
checkNotNull(selector, "Must have a selector");
checkNotNull(flag, "A flag must be set");
checkArgument(nextId != null && treatment != null, "Must supply at " +
checkArgument(nextId != null || treatment != null, "Must supply at " +
"least a treatment and/or a nextId");
checkNotNull(appId, "Must supply an application id");
return new DefaultForwardingObjective(selector, flag, permanent,
timeout, appId, priority,
nextId, treatment, Operation.REMOVE);
}
@Override
public ForwardingObjective add(ObjectiveContext context) {
checkNotNull(selector, "Must have a selector");
checkNotNull(flag, "A flag must be set");
checkArgument(nextId != null || treatment != null, "Must supply at " +
"least a treatment and/or a nextId");
checkNotNull(appId, "Must supply an application id");
return new DefaultForwardingObjective(selector, flag, permanent,
timeout, appId, priority,
nextId, treatment,
context, Operation.ADD);
}
@Override
public ForwardingObjective remove(ObjectiveContext context) {
checkNotNull(selector, "Must have a selector");
checkNotNull(flag, "A flag must be set");
checkArgument(nextId != null || treatment != null, "Must supply at " +
"least a treatment and/or a nextId");
checkNotNull(appId, "Must supply an application id");
return new DefaultForwardingObjective(selector, flag, permanent,
timeout, appId, priority,
nextId, treatment,
context, Operation.REMOVE);
}
}
}
......
......@@ -21,6 +21,7 @@ import org.onosproject.net.flow.TrafficTreatment;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -34,13 +35,28 @@ public final class DefaultNextObjective implements NextObjective {
private final ApplicationId appId;
private final Type type;
private final Integer id;
private final Operation op;
private final Optional<ObjectiveContext> context;
private DefaultNextObjective(Integer id, List<TrafficTreatment> treatments,
ApplicationId appId, Type type) {
ApplicationId appId, Type type, Operation op) {
this.treatments = treatments;
this.appId = appId;
this.type = type;
this.id = id;
this.op = op;
this.context = Optional.empty();
}
private DefaultNextObjective(Integer id, List<TrafficTreatment> treatments,
ApplicationId appId, ObjectiveContext context,
Type type, Operation op) {
this.treatments = treatments;
this.appId = appId;
this.type = type;
this.id = id;
this.op = op;
this.context = Optional.ofNullable(context);
}
@Override
......@@ -80,7 +96,12 @@ public final class DefaultNextObjective implements NextObjective {
@Override
public Operation op() {
throw new UnsupportedOperationException("Next Objective has no operation");
return op;
}
@Override
public Optional<ObjectiveContext> context() {
return context;
}
/**
......@@ -101,8 +122,6 @@ public final class DefaultNextObjective implements NextObjective {
private final ImmutableList.Builder<TrafficTreatment> listBuilder
= ImmutableList.builder();
@Override
public NextObjective.Builder withId(int nextId) {
this.id = nextId;
......@@ -143,7 +162,7 @@ public final class DefaultNextObjective implements NextObjective {
}
@Override
public Builder fromApp(ApplicationId appId) {
public NextObjective.Builder fromApp(ApplicationId appId) {
this.appId = appId;
return this;
}
......@@ -160,14 +179,49 @@ public final class DefaultNextObjective implements NextObjective {
}
@Override
public NextObjective build() {
public NextObjective add() {
List<TrafficTreatment> treatments = listBuilder.build();
checkNotNull(appId, "Must supply an application id");
checkNotNull(id, "id cannot be null");
checkNotNull(type, "The type cannot be null");
checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
return new DefaultNextObjective(id, treatments, appId, type, Operation.ADD);
}
@Override
public NextObjective remove() {
List<TrafficTreatment> treatments = listBuilder.build();
checkNotNull(appId, "Must supply an application id");
checkNotNull(id, "id cannot be null");
checkNotNull(type, "The type cannot be null");
checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
return new DefaultNextObjective(id, treatments, appId, type, Operation.REMOVE);
}
@Override
public NextObjective add(ObjectiveContext context) {
List<TrafficTreatment> treatments = listBuilder.build();
checkNotNull(appId, "Must supply an application id");
checkNotNull(id, "id cannot be null");
checkNotNull(type, "The type cannot be null");
checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
return new DefaultNextObjective(id, treatments, appId,
context, type, Operation.ADD);
}
@Override
public NextObjective remove(ObjectiveContext context) {
List<TrafficTreatment> treatments = listBuilder.build();
checkNotNull(appId, "Must supply an application id");
checkNotNull(id, "id cannot be null");
checkNotNull(type, "The type cannot be null");
checkArgument(!treatments.isEmpty(), "Must have at least one treatment");
return new DefaultNextObjective(id, treatments, appId, type);
return new DefaultNextObjective(id, treatments, appId,
context, type, Operation.REMOVE);
}
}
}
......
......@@ -114,6 +114,24 @@ public interface FilteringObjective extends Objective {
*/
public FilteringObjective remove();
/**
* Builds the filtering objective that will be added.
* The context will be used to notify the calling application.
*
* @param context an objective context
* @return a filtering objective
*/
public FilteringObjective add(ObjectiveContext context);
/**
* Builds the filtering objective that will be removed.
* The context will be used to notify the calling application.
*
* @param context an objective context
* @return a filtering objective
*/
public FilteringObjective remove(ObjectiveContext context);
}
......
......@@ -17,9 +17,6 @@ package org.onosproject.net.flowobjective;
import org.onosproject.net.DeviceId;
import java.util.Collection;
import java.util.concurrent.Future;
/**
* Service for programming data plane flow rules in manner independent of
* specific device table pipeline configuration.
......@@ -30,27 +27,24 @@ public interface FlowObjectiveService {
* Installs the filtering rules onto the specified device.
*
* @param deviceId device identifier
* @param filteringObjectives the collection of filters
* @return a future indicating the success of the operation
* @param filteringObjective the filtering objective
*/
Future<Boolean> filter(DeviceId deviceId, Collection<FilteringObjective> filteringObjectives);
void filter(DeviceId deviceId, FilteringObjective filteringObjective);
/**
* Installs the forwarding rules onto the specified device.
*
* @param deviceId device identifier
* @param forwardingObjectives the collection of forwarding objectives
* @return a future indicating the success of the operation
* @param forwardingObjective the forwarding objective
*/
Future<Boolean> forward(DeviceId deviceId, Collection<ForwardingObjective> forwardingObjectives);
void forward(DeviceId deviceId, ForwardingObjective forwardingObjective);
/**
* Installs the next hop elements into the specified device.
*
* @param deviceId device identifier
* @param nextObjectives the collection of next objectives
* @return a future indicating the success of the operation
* @param nextObjective a next objective
*/
Future<Boolean> next(DeviceId deviceId, Collection<NextObjective> nextObjectives);
void next(DeviceId deviceId, NextObjective nextObjective);
}
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.flowobjective;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.store.Store;
/**
* The flow objective store.
*/
public interface FlowObjectiveStore
extends Store<ObjectiveEvent, FlowObjectiveStoreDelegate> {
/**
* Adds a NextGroup to the store.
*
* @param nextId an integer
* @param group a next group opaque object
*/
void putNextGroup(Integer nextId, NextGroup group);
/**
* Fetch a next group from the store.
* @param nextId an integer
* @return a next group
*/
NextGroup getNextGroup(Integer nextId);
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.flowobjective;
import org.onosproject.store.StoreDelegate;
/**
* Flow Objective store delegate abstraction.
*/
public interface FlowObjectiveStoreDelegate extends StoreDelegate<ObjectiveEvent> {
}
......@@ -121,5 +121,23 @@ public interface ForwardingObjective extends Objective {
* @return a forwarding objective.
*/
public ForwardingObjective remove();
/**
* Builds the forwarding objective that will be added.
* The context will be used to notify the calling application.
*
* @param context an objective context
* @return a forwarding objective
*/
public ForwardingObjective add(ObjectiveContext context);
/**
* Builds the forwarding objective that will be removed.
* The context will be used to notify the calling application.
*
* @param context an objective context
* @return a forwarding objective
*/
public ForwardingObjective remove(ObjectiveContext context);
}
}
......
......@@ -15,6 +15,7 @@
*/
package org.onosproject.net.flowobjective;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.flow.TrafficTreatment;
import java.util.Collection;
......@@ -95,12 +96,40 @@ public interface NextObjective extends Objective {
*/
public Builder addTreatment(TrafficTreatment treatment);
@Override
public Builder fromApp(ApplicationId appId);
/**
* Builds the next objective that will be added.
*
* @return a next objective
*/
public NextObjective add();
/**
* Builds the next objective that will be removed.
*
* @return a next objective.
*/
public NextObjective remove();
/**
* Builds the next objective that will be added.
* The context will be used to notify the calling application.
*
* @param context an objective context
* @return a next objective
*/
public NextObjective add(ObjectiveContext context);
/**
* Builds a next step.
* Builds the next objective that will be removed.
* The context will be used to notify the calling application.
*
* @return a next step
* @param context an objective context
* @return a next objective
*/
public NextObjective build();
public NextObjective remove(ObjectiveContext context);
}
......
......@@ -17,6 +17,8 @@ package org.onosproject.net.flowobjective;
import org.onosproject.core.ApplicationId;
import java.util.Optional;
/**
* Base representation of an flow description.
*/
......@@ -84,6 +86,14 @@ public interface Objective {
Operation op();
/**
* Obtains an optional context.
*
* @return optional; which will be empty if there is no context.
* Otherwise it will return the context.
*/
Optional<ObjectiveContext> context();
/**
* An objective builder.
*/
public interface Builder {
......
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.flowobjective;
/**
* The context of a objective that will become the subject of
* the notification.
*
* Implementations of this class must be serializable.
*/
public interface ObjectiveContext {
default void onSuccess(Objective objective) {}
default void onError(Objective objective, ObjectiveError error) {}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.flowobjective;
/**
* Represents the set of errors possible when processing an objective.
*/
public enum ObjectiveError {
/**
* The driver processing this objective does not know how to process it.
*/
UNSUPPORTED,
/**
* The flow installation for this objective failed.
*/
FLOWINSTALLATIONFAILED,
/**
* THe group installation for this objective failed.
*/
GROUPINSTALLATIONFAILED,
/**
* The group was reported as installed but is not missing.
*/
GROUPMISSING,
/**
* An unknown error occurred.
*/
UNKNOWN
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.flowobjective;
import org.onosproject.event.AbstractEvent;
/**
* Describes a objective event.
*/
public class ObjectiveEvent extends AbstractEvent<ObjectiveEvent.Type, Integer> {
/**
* Type of objective events.
*/
public enum Type {
/**
* Signifies that the objective has been added to the store.
*/
ADD,
/**
* Signifies that the objective has been removed.
*/
REMOVE
}
/**
* Creates an event of the given type for the specified objective id.
*
* @param type the type of the event
* @param objective the objective id the event is about
*/
public ObjectiveEvent(Type type, Integer objective) {
super(type, objective);
}
/**
* Creates an event of the given type for the specified objective id at the given
* time.
*
* @param type the type of the event
* @param objective the objective id the event is about
* @param time the time of the event
*/
public ObjectiveEvent(Type type, Integer objective, long time) {
super(type, objective, time);
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.flowobjective.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.behaviour.DefaultNextGroup;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
import org.onosproject.net.flowobjective.ObjectiveEvent;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages the inventory of created next groups.
*/
@Component(immediate = true, enabled = true)
@Service
public class DistributedFlowObjectiveStore
extends AbstractStore<ObjectiveEvent, FlowObjectiveStoreDelegate>
implements FlowObjectiveStore {
private final Logger log = getLogger(getClass());
private ConsistentMap<Integer, byte[]> nextGroups;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@Activate
public void activate() {
nextGroups = storageService.<Integer, byte[]>consistentMapBuilder()
.withName("flowobjective-groups")
.withSerializer(Serializer.using(
new KryoNamespace.Builder()
.register(byte[].class)
.build()))
.build();
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
@Override
public void putNextGroup(Integer nextId, NextGroup group) {
nextGroups.putIfAbsent(nextId, group.data());
notifyDelegate(new ObjectiveEvent(ObjectiveEvent.Type.ADD, nextId));
}
@Override
public NextGroup getNextGroup(Integer nextId) {
Versioned<byte[]> versionGroup = nextGroups.get(nextId);
if (versionGroup != null) {
return new DefaultNextGroup(versionGroup.value());
}
return null;
}
}
......@@ -167,10 +167,13 @@ public class DistributedPacketStore
public PacketRequestTracker() {
requests = storageService.<PacketRequest, Boolean>consistentMapBuilder()
.withName("packet-requests")
.withSerializer(Serializer.using(
new KryoNamespace.Builder().register(KryoNamespaces.API).build()))
.withSerializer(new Serializer() {
KryoNamespace kryo = new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.build();
@Override
public <T> byte[] encode(T object) {
return kryo.serialize(object);
......
......@@ -44,6 +44,12 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>1.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
......
......@@ -31,11 +31,9 @@ import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.concurrent.Future;
import static org.slf4j.LoggerFactory.getLogger;
/**
......@@ -58,59 +56,62 @@ public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour impleme
}
@Override
public Future<Boolean> filter(Collection<FilteringObjective> filters) {
public void filter(FilteringObjective filter) {
throw new UnsupportedOperationException("Single table does not filter.");
}
@Override
public Future<Boolean> forward(Collection<ForwardingObjective> forwardings) {
public void forward(ForwardingObjective fwd) {
FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
forwardings.forEach(fwd -> {
if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
throw new UnsupportedOperationException(
"Only VERSATILE is supported.");
}
TrafficSelector selector = fwd.selector();
if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) {
throw new UnsupportedOperationException(
"Only VERSATILE is supported.");
}
FlowRule rule = new DefaultFlowRule(deviceId, selector,
fwd.treatment(),
fwd.priority(), fwd.appId(),
new DefaultGroupId(fwd.id()),
fwd.timeout(), fwd.permanent());
TrafficSelector selector = fwd.selector();
switch (fwd.op()) {
FlowRule rule = new DefaultFlowRule(deviceId, selector,
fwd.treatment(),
fwd.priority(), fwd.appId(),
new DefaultGroupId(fwd.id()),
fwd.timeout(), fwd.permanent());
case ADD:
flowBuilder.add(rule);
break;
case REMOVE:
flowBuilder.remove(rule);
break;
default:
log.warn("Unknown operation {}", fwd.op());
}
switch (fwd.op()) {
case ADD:
flowBuilder.add(rule);
break;
case REMOVE:
flowBuilder.remove(rule);
break;
default:
log.warn("Unknown operation {}", fwd.op());
}
});
SettableFuture<Boolean> future = SettableFuture.create();
flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
future.set(true);
if (fwd.context().isPresent()) {
fwd.context().get().onSuccess(fwd);
}
}
@Override
public void onError(FlowRuleOperations ops) {
future.set(false);
if (fwd.context().isPresent()) {
fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
}
}
}));
return future;
}
@Override
public Future<Boolean> next(Collection<NextObjective> nextObjectives) {
public void next(NextObjective nextObjective) {
throw new UnsupportedOperationException("Single table does not next hop.");
}
......
......@@ -19,7 +19,7 @@
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
</driver>
<driver name="ovs-corsa" manufacturer="Nicira, Inc." hwVersion="Open vSwitch" swVersion="2.3.0">
<driver name="ovs-corsa" manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
</driver>
......
......@@ -195,7 +195,6 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
for (Instruction i : treatments) {
switch (i.type()) {
case DROP:
log.warn("Saw drop action; assigning drop action");
return new LinkedList<>();
case L0MODIFICATION:
actions.add(buildL0Modification(i));
......