aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core
diff options
context:
space:
mode:
authorAshlee Young <ashlee@wildernessvoice.com>2015-11-03 14:08:10 -0800
committerAshlee Young <ashlee@wildernessvoice.com>2015-11-03 14:08:10 -0800
commit643ee33289bd2cb9e6afbfb09b4ed72d467ba1c2 (patch)
treec2c376a44a359544fe3d4c45eb0cc0e2ec4a7080 /framework/src/onos/core
parent46eeb79b54345bdafb6055b8ee4bad4ce8b01274 (diff)
This updates ONOS src tree to commit id
03fa5e571cabbd001ddb1598847e1150b11c7333 Change-Id: I13b554026d6f902933e35887d29bd5fdb669c0bd Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/core')
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java3
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java185
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java7
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java91
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java11
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java9
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java19
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java71
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionPropertyException.java (renamed from framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java)26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java92
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java7
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java16
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java14
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java17
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java8
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java8
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java13
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java104
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java54
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java19
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java4
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java8
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java1
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java2
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java54
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java93
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java51
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java59
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java42
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java35
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java14
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java37
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java3
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java33
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java56
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java48
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java25
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java58
-rw-r--r--framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json5
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java48
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java116
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java2
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java24
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java110
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java3
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java108
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java13
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java98
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java100
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java15
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java395
-rw-r--r--framework/src/onos/core/store/dist/pom.xml2
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java58
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java194
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java63
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java11
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java221
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java6
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java7
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java108
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java74
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java52
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java9
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java20
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java2
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java14
-rw-r--r--framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java6
-rw-r--r--framework/src/onos/core/store/persistence/pom.xml66
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java63
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java59
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java30
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java138
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java192
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java194
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java20
-rw-r--r--framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java245
-rw-r--r--framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java274
-rw-r--r--framework/src/onos/core/store/pom.xml3
-rw-r--r--framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java73
-rw-r--r--framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java13
100 files changed, 4498 insertions, 972 deletions
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
index 5f2b5fff..47944874 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
@@ -30,9 +30,8 @@ public interface ClusterAdminService {
* instance.
*
* @param nodes set of nodes that form the cluster
- * @param ipPrefix IP address prefix, e.g. 10.0.1.*
*/
- void formCluster(Set<ControllerNode> nodes, String ipPrefix);
+ void formCluster(Set<ControllerNode> nodes);
/**
* Adds a new controller node to the cluster.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
deleted file mode 100644
index 1ee78b15..00000000
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.cluster;
-
-import java.util.Set;
-
-/**
- * Service for obtaining the static definition of a controller cluster.
- */
-public interface ClusterDefinitionService {
-
- /**
- * Returns the local controller node.
- * @return local controller node
- */
- ControllerNode localNode();
-
- /**
- * Returns the set of seed nodes that should be used for discovering other members
- * of the cluster.
- * @return set of seed controller nodes
- */
- Set<ControllerNode> seedNodes();
-
- /**
- * Forms cluster configuration based on the specified set of node
- * information. Assumes subsequent restart for the new configuration to
- * take hold.
- *
- * @param nodes set of nodes that form the cluster
- * @param ipPrefix IP address prefix, e.g. 10.0.1.*
- */
- void formCluster(Set<ControllerNode> nodes, String ipPrefix);
-} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
new file mode 100644
index 00000000..e1eacfee
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
@@ -0,0 +1,185 @@
+/*
+ * 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.cluster;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Verify.verifyNotNull;
+import static com.google.common.base.Verify.verify;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * Cluster metadata.
+ * <p>
+ * Metadata specifies the attributes that define a ONOS cluster and comprises the collection
+ * of {@link org.onosproject.cluster.ControllerNode nodes} and the collection of data
+ * {@link org.onosproject.cluster.Partition partitions}.
+ */
+public final class ClusterMetadata {
+
+ private String name;
+ private Set<ControllerNode> nodes;
+ private Set<Partition> partitions;
+
+ /**
+ * Returns a new cluster metadata builder.
+ * @return The cluster metadata builder.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns the name of the cluster.
+ *
+ * @return cluster name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the collection of {@link org.onosproject.cluster.ControllerNode nodes} that make up the cluster.
+ * @return cluster nodes
+ */
+ public Collection<ControllerNode> getNodes() {
+ return this.nodes;
+ }
+
+ /**
+ * Returns the collection of data {@link org.onosproject.cluster.Partition partitions} that make up the cluster.
+ * @return collection of partitions.
+ */
+ public Collection<Partition> getPartitions() {
+ return this.partitions;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(ClusterMetadata.class)
+ .add("name", name)
+ .add("nodes", nodes)
+ .add("partitions", partitions)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.deepHashCode(new Object[] {name, nodes, partitions});
+ }
+
+ /*
+ * Provide a deep quality check of the meta data (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object object) {
+
+ if (!ClusterMetadata.class.isInstance(object)) {
+ return false;
+ }
+ ClusterMetadata that = (ClusterMetadata) object;
+
+ if (!this.name.equals(that.name) || this.nodes.size() != that.nodes.size()
+ || this.partitions.size() != that.partitions.size()) {
+ return false;
+ }
+
+ return Sets.symmetricDifference(this.nodes, that.nodes).isEmpty()
+ && Sets.symmetricDifference(this.partitions, that.partitions).isEmpty();
+ }
+
+ /**
+ * Builder for a {@link ClusterMetadata} instance.
+ */
+ public static class Builder {
+
+ private final ClusterMetadata metadata;
+
+ public Builder() {
+ metadata = new ClusterMetadata();
+ }
+
+ /**
+ * Sets the cluster name, returning the cluster metadata builder for method chaining.
+ * @param name cluster name
+ * @return this cluster metadata builder
+ */
+ public Builder withName(String name) {
+ metadata.name = checkNotNull(name);
+ return this;
+ }
+
+ /**
+ * Sets the collection of cluster nodes, returning the cluster metadata builder for method chaining.
+ * @param controllerNodes collection of cluster nodes
+ * @return this cluster metadata builder
+ */
+ public Builder withControllerNodes(Collection<ControllerNode> controllerNodes) {
+ metadata.nodes = ImmutableSet.copyOf(checkNotNull(controllerNodes));
+ return this;
+ }
+
+ /**
+ * Sets the collection of data partitions, returning the cluster metadata builder for method chaining.
+ * @param partitions collection of partitions
+ * @return this cluster metadata builder
+ */
+ public Builder withPartitions(Collection<Partition> partitions) {
+ metadata.partitions = ImmutableSet.copyOf(checkNotNull(partitions));
+ return this;
+ }
+
+ /**
+ * Builds the cluster metadata.
+ * @return cluster metadata
+ * @throws com.google.common.base.VerifyException VerifyException if the metadata is misconfigured
+ */
+ public ClusterMetadata build() {
+ verifyMetadata();
+ return metadata;
+ }
+
+ /**
+ * Validates the constructed metadata for semantic correctness.
+ * @throws VerifyException if the metadata is misconfigured.
+ */
+ private void verifyMetadata() {
+ verifyNotNull(metadata.getName(), "Cluster name must be specified");
+ verifyNotNull(metadata.getNodes(), "Cluster nodes must be specified");
+ verifyNotNull(metadata.getPartitions(), "Cluster partitions must be specified");
+ verify(!metadata.getNodes().isEmpty(), "Cluster nodes must not be empty");
+ verify(!metadata.getPartitions().isEmpty(), "Cluster nodes must not be empty");
+
+ // verify that partitions are constituted from valid cluster nodes.
+ boolean validPartitions = Collections2.transform(metadata.getNodes(), ControllerNode::id)
+ .containsAll(metadata.getPartitions()
+ .stream()
+ .flatMap(r -> r.getMembers().stream())
+ .collect(Collectors.toSet()));
+ verify(validPartitions, "Partition locations must be valid cluster nodes");
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java
new file mode 100644
index 00000000..a0f461c4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java
@@ -0,0 +1,56 @@
+/*
+ * 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.cluster;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a cluster metadata event.
+ */
+public class ClusterMetadataEvent extends AbstractEvent<ClusterMetadataEvent.Type, ClusterMetadata> {
+
+ /**
+ * Type of cluster metadata events.
+ */
+ public enum Type {
+ /**
+ * Signifies that the cluster metadata has changed.
+ */
+ METADATA_CHANGED,
+ }
+
+ /**
+ * Creates an event of a given type and for the specified metadata and the
+ * current time.
+ *
+ * @param type cluster metadata event type
+ * @param metadata cluster metadata subject
+ */
+ public ClusterMetadataEvent(Type type, ClusterMetadata metadata) {
+ super(type, metadata);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified metadata and time.
+ *
+ * @param type cluster metadata event type
+ * @param metadata cluster metadata subject
+ * @param time occurrence time
+ */
+ public ClusterMetadataEvent(Type type, ClusterMetadata metadata, long time) {
+ super(type, metadata, time);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java
new file mode 100644
index 00000000..fdfaeed0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving cluster metadata related events.
+ */
+public interface ClusterMetadataEventListener extends EventListener<ClusterMetadataEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java
new file mode 100644
index 00000000..25a6df63
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cluster;
+
+/**
+ * Service for obtaining metadata information about the cluster.
+ */
+public interface ClusterMetadataService {
+
+ /**
+ * Returns the current cluster metadata.
+ * @return cluster metadata
+ */
+ ClusterMetadata getClusterMetadata();
+
+ /**
+ * Updates the cluster metadata.
+ * @param metadata new metadata
+ */
+ void setClusterMetadata(ClusterMetadata metadata);
+
+ /**
+ * Returns the local controller node representing this instance.
+ * @return local controller node
+ */
+ ControllerNode getLocalNode();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java
new file mode 100644
index 00000000..7e83b5b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java
@@ -0,0 +1,77 @@
+/*
+ * 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.cluster;
+
+import java.util.Collection;
+
+import org.onosproject.store.Store;
+import org.onosproject.store.service.Versioned;
+
+/**
+ * Manages persistence of cluster metadata; not intended for direct use.
+ */
+public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, ClusterMetadataStoreDelegate> {
+
+ /**
+ * Returns the cluster metadata.
+ * <p>
+ * The returned metadata is versioned to aid determining if a metadata instance is more recent than another.
+ * @return cluster metadata
+ */
+ Versioned<ClusterMetadata> getClusterMetadata();
+
+ /**
+ * Updates the cluster metadata.
+ * @param metadata new metadata value
+ */
+ void setClusterMetadata(ClusterMetadata metadata);
+
+ // TODO: The below methods should move to a separate store interface that is responsible for
+ // tracking cluster partition operational state.
+
+ /**
+ * Sets a controller node as an active member of a partition.
+ * <p>
+ * Active members are those replicas that are up to speed with the rest of the system and are
+ * usually capable of participating in the replica state management activities in accordance with
+ * the data consistency and replication protocol in use.
+ * @param partitionId partition identifier
+ * @param nodeId id of controller node
+ */
+ void setActiveReplica(String partitionId, NodeId nodeId);
+
+ /**
+ * Removes a controller node as an active member for a partition.
+ * <p>
+ * Active members are those replicas that are up to speed with the rest of the system and are
+ * usually capable of participating in the replica state management activities in accordance with
+ * the data consistency and replication protocol in use.
+ * @param partitionId partition identifier
+ * @param nodeId id of controller node
+ */
+ void unsetActiveReplica(String partitionId, NodeId nodeId);
+
+ /**
+ * Returns the collection of controller nodes that are the active replicas for a partition.
+ * <p>
+ * Active members are those replicas that are up to speed with the rest of the system and are
+ * usually capable of participating in the replica state management activities in accordance with
+ * the data consistency and replication protocol in use.
+ * @param partitionId partition identifier
+ * @return identifiers of controller nodes that are the active replicas
+ */
+ Collection<NodeId> getActiveReplicas(String partitionId);
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java
new file mode 100644
index 00000000..b56b7a24
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Cluster metadata store delegate abstraction.
+ */
+public interface ClusterMetadataStoreDelegate extends StoreDelegate<ClusterMetadataEvent> {
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
index 68b490f2..6cfb42c7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
@@ -20,7 +20,7 @@ import java.util.Objects;
/**
* Controller cluster identity.
*/
-public class NodeId {
+public class NodeId implements Comparable<NodeId> {
private final String id;
@@ -55,4 +55,9 @@ public class NodeId {
return id;
}
+ @Override
+ public int compareTo(NodeId that) {
+ return this.id.compareTo(that.id);
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java
new file mode 100644
index 00000000..1eca4aeb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java
@@ -0,0 +1,91 @@
+/*
+ * 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.cluster;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A data partition.
+ * <p>
+ * Partition represents a slice of the data space and is made up of a collection
+ * of {@link org.onosproject.cluster.ControllerNode nodes}
+ * that all maintain copies of this data.
+ */
+public class Partition {
+
+ private final String name;
+ private final Set<NodeId> members;
+
+ private Partition() {
+ name = null;
+ members = null;
+ }
+
+ public Partition(String name, Collection<NodeId> members) {
+ this.name = checkNotNull(name);
+ this.members = ImmutableSet.copyOf(checkNotNull(members));
+ }
+
+ /**
+ * Returns the partition name.
+ * <p>
+ * Each partition is identified by a unique name.
+ * @return partition name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the collection of controller node identifiers that make up this partition.
+ * @return collection of controller node identifiers
+ */
+ public Collection<NodeId> getMembers() {
+ return this.members;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.deepHashCode(new Object[] {name, members});
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || !Partition.class.isInstance(other)) {
+ return false;
+ }
+
+ Partition that = (Partition) other;
+
+ if (!this.name.equals(that.name) || (this.members == null && that.members != null)
+ || (this.members != null && that.members == null) || this.members.size() != that.members.size()) {
+ return false;
+ }
+
+ return Sets.symmetricDifference(this.members, that.members).isEmpty();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
index 7f157e95..e3d6993c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
@@ -36,6 +36,17 @@ public interface BridgeConfig extends HandlerBehaviour {
void addBridge(BridgeName bridgeName);
/**
+ * Adds a bridge with given bridge name and dpid, and sets the controller
+ * of the bridge with given controllers.
+ *
+ * @param bridgeName bridge name
+ * @param dpid dpid
+ * @param controllers list of controller
+ * @return true if succeeds, fail otherwise
+ */
+ boolean addBridge(BridgeName bridgeName, String dpid, List<ControllerInfo> controllers);
+
+ /**
* Remove a bridge.
*
* @param bridgeName bridge name
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java
new file mode 100644
index 00000000..54cbc7ac
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+
+/**
+ * Provides access to the extension implemented by this driver.
+ */
+@Beta
+public interface ExtensionResolver extends HandlerBehaviour {
+
+ /**
+ * Gets an extension instruction instance of the specified type, if supported
+ * by the driver.
+ *
+ * @param type type of extension to get
+ * @return extension instruction
+ * @throws UnsupportedOperationException if the extension type is not
+ * supported by this driver
+ */
+ ExtensionInstruction getExtensionInstruction(ExtensionType type);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
index 7e79a57e..e3b4c198 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
@@ -32,6 +32,15 @@ public interface TunnelConfig extends HandlerBehaviour {
void createTunnel(TunnelDescription tunnel);
/**
+ * Creates a tunnel interface on a given bridge of this device.
+ *
+ * @param bridgeName bridge name
+ * @param tunnel tunnel description
+ * @return true if succeeds, false otherwise
+ */
+ boolean createTunnelInterface(BridgeName bridgeName, TunnelDescription tunnel);
+
+ /**
* Removes a tunnel on this device.
*
* @param tunnel tunnel descriptor
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
index 4416456c..453a7648 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
@@ -15,8 +15,14 @@
*/
package org.onosproject.net.flow;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -27,13 +33,8 @@ import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
/**
* Default traffic selector implementation.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index 6174cef6..6beeecc9 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -15,9 +15,11 @@
*/
package org.onosproject.net.flow;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Objects;
+
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
@@ -25,16 +27,17 @@ import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.meter.MeterId;
-import java.util.List;
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
/**
* Default traffic treatment implementation.
@@ -239,9 +242,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
case GROUP:
case QUEUE:
case L0MODIFICATION:
+ case L1MODIFICATION:
case L2MODIFICATION:
case L3MODIFICATION:
case L4MODIFICATION:
+ case EXTENSION:
current.add(instruction);
break;
case TABLE:
@@ -479,6 +484,12 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
}
@Override
+ public TrafficTreatment.Builder extension(ExtensionInstruction extension,
+ DeviceId deviceId) {
+ return add(Instructions.extension(extension, deviceId));
+ }
+
+ @Override
public TrafficTreatment build() {
if (deferred.size() == 0 && immediate.size() == 0
&& table == null && !clear) {
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index c7fe8b85..b14ab99c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.net.flow;
+import java.util.List;
+
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
@@ -22,13 +24,13 @@ import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.meter.MeterId;
-import java.util.List;
-
/**
* Abstraction of network traffic treatment.
*/
@@ -413,6 +415,15 @@ public interface TrafficTreatment {
Builder setUdpDst(TpPort port);
/**
+ * Uses an extension treatment.
+ *
+ * @param extension extension treatment
+ * @param deviceId device ID
+ * @return a treatment builder
+ */
+ Builder extension(ExtensionInstruction extension, DeviceId deviceId);
+
+ /**
* Builds an immutable traffic treatment descriptor.
* <p>
* If the treatment is empty when build() is called, it will add a default
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java
new file mode 100644
index 00000000..9f22f888
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java
@@ -0,0 +1,71 @@
+/*
+ * 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.flow.instructions;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract implementation of the set/get property methods of ExtensionInstruction.
+ */
+public abstract class AbstractExtensionInstruction implements ExtensionInstruction {
+
+ private static final String INVALID_KEY = "Invalid property key: ";
+ private static final String INVALID_TYPE = "Given type does not match field type: ";
+
+ @Override
+ public <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException {
+ Class<?> clazz = this.getClass();
+ try {
+ Field field = clazz.getDeclaredField(key);
+ field.setAccessible(true);
+ field.set(this, value);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExtensionPropertyException(INVALID_KEY + key);
+ }
+ }
+
+ @Override
+ public <T> T getPropertyValue(String key) throws ExtensionPropertyException {
+ Class<?> clazz = this.getClass();
+ try {
+ Field field = clazz.getDeclaredField(key);
+ field.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ T result = (T) field.get(this);
+ return result;
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExtensionPropertyException(INVALID_KEY + key);
+ } catch (ClassCastException e) {
+ throw new ExtensionPropertyException(INVALID_TYPE + key);
+ }
+ }
+
+ @Override
+ public List<String> getProperties() {
+ Class<?> clazz = this.getClass();
+
+ List<String> fields = new ArrayList<>();
+
+ for (Field field : clazz.getDeclaredFields()) {
+ fields.add(field.getName());
+ }
+
+ return fields;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java
new file mode 100644
index 00000000..89e0cc5e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java
@@ -0,0 +1,78 @@
+/*
+ * 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.flow.instructions;
+
+import java.util.List;
+
+/**
+ * An extensible instruction type.
+ */
+public interface ExtensionInstruction {
+
+ /**
+ * Gets the type of the extension instruction.
+ *
+ * @return type
+ */
+ ExtensionType type();
+
+ /**
+ * Sets a property on the extension instruction.
+ *
+ * @param key property key
+ * @param value value to set for the given key
+ * @param <T> class of the value
+ * @throws ExtensionPropertyException if the given key is not a valid
+ * property on this extension instruction
+ */
+ <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException;
+
+ /**
+ * Gets a property value of an extension instruction.
+ *
+ * @param key property key
+ * @param <T> class of the value
+ * @return value of the property
+ * @throws ExtensionPropertyException if the given key is not a valid
+ * property on this extension instruction
+ */
+ <T> T getPropertyValue(String key) throws ExtensionPropertyException;
+
+ /**
+ * Gets a list of all properties on the extension instruction.
+ *
+ * @return list of properties
+ */
+ List<String> getProperties();
+
+ /**
+ * Serialize the extension instruction to a byte array.
+ *
+ * @return byte array
+ */
+ byte[] serialize();
+
+ /**
+ * Deserialize the extension instruction from a byte array. The properties
+ * of this object will be overwritten with the data in the byte array.
+ *
+ * @param data input byte array
+ */
+ void deserialize(byte[] data);
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionPropertyException.java
index a77079ce..5750d09e 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionPropertyException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * 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.
@@ -13,24 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.flow;
-import org.onosproject.net.PortNumber;
+package org.onosproject.net.flow.instructions;
/**
- * Abstraction of different kinds of treatment that can be applied to an
- * outbound packet.
+ * Exception indicating there was an error while setting/getting an extension
+ * instruction property.
*/
-public interface Treatment {
+public class ExtensionPropertyException extends Exception {
- // TODO: implement these later: modifications, group
- // TODO: elsewhere provide factory methods for some default treatments
-
- /**
- * Returns the port number where the packet should be emitted.
- *
- * @return output port number
- */
- PortNumber output();
+ public ExtensionPropertyException(String message) {
+ super(message);
+ }
+ public ExtensionPropertyException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java
new file mode 100644
index 00000000..747a85b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java
@@ -0,0 +1,92 @@
+/*
+ * 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.flow.instructions;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Type of extension instructions.
+ */
+@Beta
+public final class ExtensionType {
+
+ /**
+ * A list of well-known named extension instruction type codes.
+ */
+ public enum ExtensionTypes {
+ // TODO fix type numbers to include experimenter id
+ NICIRA_SET_TUNNEL_DST(31);
+
+ private ExtensionType type;
+
+ /**
+ * Creates a new named extension instruction type.
+ *
+ * @param type type code
+ */
+ ExtensionTypes(int type) {
+ this.type = new ExtensionType(type);
+ }
+
+ /**
+ * Gets the extension type object for this named type code.
+ *
+ * @return extension type object
+ */
+ public ExtensionType type() {
+ return type;
+ }
+ }
+
+ private final int type;
+
+ /**
+ * Creates an extension type with the given int type code.
+ *
+ * @param type type code
+ */
+ public ExtensionType(int type) {
+ this.type = type;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ExtensionType) {
+ final ExtensionType that = (ExtensionType) obj;
+ return this.type == that.type;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(ExtensionType.class)
+ .add("type", type)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
index 2f6a1cc1..31ad80c5 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
@@ -92,7 +92,12 @@ public interface Instruction {
/**
* Signifies that the traffic should be modified in L4 way.
*/
- L4MODIFICATION
+ L4MODIFICATION,
+
+ /**
+ * Signifies that an extension instruction will be used.
+ */
+ EXTENSION
}
/**
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 8868bf7c..aad407c8 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -22,6 +22,7 @@ import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
@@ -480,6 +481,20 @@ public final class Instructions {
}
/**
+ * Creates an extension instruction.
+ *
+ * @param extension extension instruction
+ * @param deviceId device ID
+ * @return extension instruction
+ */
+ public static ExtensionInstructionWrapper extension(ExtensionInstruction extension,
+ DeviceId deviceId) {
+ checkNotNull(extension, "Extension instruction cannot be null");
+ checkNotNull(deviceId, "Device ID cannot be null");
+ return new ExtensionInstructionWrapper(extension, deviceId);
+ }
+
+ /**
* Drop instruction.
*/
@Deprecated
@@ -820,6 +835,59 @@ public final class Instructions {
}
}
+ /**
+ * Extension instruction.
+ */
+ public static class ExtensionInstructionWrapper implements Instruction {
+ private final ExtensionInstruction extensionInstruction;
+ private final DeviceId deviceId;
+
+ ExtensionInstructionWrapper(ExtensionInstruction extension, DeviceId deviceId) {
+ extensionInstruction = extension;
+ this.deviceId = deviceId;
+ }
+
+ public ExtensionInstruction extensionInstruction() {
+ return extensionInstruction;
+ }
+
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.EXTENSION;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("extension", extensionInstruction)
+ .add("deviceId", deviceId)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), extensionInstruction, deviceId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ExtensionInstructionWrapper) {
+ ExtensionInstructionWrapper that = (ExtensionInstructionWrapper) obj;
+ return Objects.equals(extensionInstruction, that.extensionInstruction)
+ && Objects.equals(deviceId, that.deviceId);
+
+ }
+ return false;
+ }
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
index 7b5924fb..06305bf7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
@@ -18,6 +18,7 @@ package org.onosproject.net.flowobjective;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
@@ -46,6 +47,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
private final int id;
private final Operation op;
private final Optional<ObjectiveContext> context;
+ private final TrafficTreatment meta;
private DefaultFilteringObjective(Builder builder) {
this.key = builder.key;
@@ -57,6 +59,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
this.conditions = builder.conditions;
this.op = builder.op;
this.context = Optional.ofNullable(builder.context);
+ this.meta = builder.meta;
this.id = Objects.hash(type, key, conditions, permanent,
timeout, appId, priority);
@@ -83,6 +86,12 @@ public final class DefaultFilteringObjective implements FilteringObjective {
}
@Override
+ public TrafficTreatment meta() {
+ return meta;
+ }
+
+
+ @Override
public int priority() {
return priority;
}
@@ -135,6 +144,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
private List<Criterion> conditions;
private Operation op;
private ObjectiveContext context;
+ private TrafficTreatment meta;
@Override
public Builder withKey(Criterion key) {
@@ -186,6 +196,12 @@ public final class DefaultFilteringObjective implements FilteringObjective {
}
@Override
+ public Builder setMeta(TrafficTreatment treatment) {
+ this.meta = treatment;
+ return this;
+ }
+
+ @Override
public FilteringObjective add() {
conditions = listBuilder.build();
op = Operation.ADD;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
index 58304571..29257c61 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
@@ -17,49 +17,54 @@ package org.onosproject.net.flowobjective;
import com.google.common.annotations.Beta;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import java.util.Collection;
/**
* Represents a filtering flow objective. Each filtering flow objective
- * is made up of a key (criterion) to a set of criteria. Using this information
- * a pipeline aware driver will decide how this objective should be mapped
- * to the specific device pipeline. For example, consider the following
- * filtering objective:
- *
- * portX -&gt; {MAC1, IP1, MAC2}
- *
- * The driver could decide to pass L3 packet to the L3 table and L2 packets to
- * the L2 table for packets arriving on portX.
- *
- * Filtering objectives do not only represent what should be permitted into the
- * pipeline but can also be used to deny or drop unwanted packets by specifying
- * the appropriate type of filtering objective. It is also important to note
- * that submitting a filtering objective does not necessarily result in rules
- * programmed at the switch, the driver is free to decide when these rules are
- * programmed. For example, a filtering rule may only be programmed once a
- * corresponding forwarding objective has been received.
+ * is made up of a key (typically a PortCriterion) mapped to a set of criteria.
+ * Using this information, a pipeline aware driver will decide how this objective
+ * should be mapped to the device specific pipeline-tables in order to satisfy the
+ * filtering condition. For example, consider the following PERMIT filtering
+ * objective:
+ * <p>
+ * portX -&gt; {MAC1, VLAN1}
+ * <p>
+ * The driver could decide to pass packets to the MAC table or VLAN or PORT
+ * tables to ensure that only those packets arriving with the correct dst MAC
+ * and VLAN ids from Port X are allowed into the pipeline.
+ * <p>
+ * Filtering objectives of type PERMIT allow packets that match the key:criteria
+ * to enter the pipeline. As a result, the implication is that packets that don't
+ * match are automatically denied (dropped).
+ * <p>
+ * Filtering objectives of type DENY, are used to deny packets that would
+ * otherwise be permitted and forwarded through the pipeline (ie. those packets
+ * that make it through the PERMIT filters).
*/
@Beta
public interface FilteringObjective extends Objective {
enum Type {
/**
- * Enables the filtering condition.
+ * Permits packets that match the filtering condition to be processed
+ * by the rest of the pipeline. Automatically denies packets that don't
+ * match the criteria.
*/
PERMIT,
/**
- * Disables the filtering condition.
+ * Denies packets that make it through the permit filters.
*/
DENY
}
/**
- * Obtain the key for this filter.
+ * Obtain the key for this filter. The filter may or may not require a key.
*
- * @return a criterion
+ * @return a criterion, which could be null if no key was provided.
*/
Criterion key();
@@ -78,6 +83,16 @@ public interface FilteringObjective extends Objective {
Collection<Criterion> conditions();
/**
+ * Auxiliary optional information provided to the device-driver.Typically
+ * conveys information about changes (treatments) to packets that are
+ * permitted into the pipeline by the PERMIT filtering condition.
+ *
+ * @return a treatment on the packets that make it through the PERMIT filters.
+ * Value may be null if no meta information is provided.
+ */
+ TrafficTreatment meta();
+
+ /**
* Builder of Filtering objective entities.
*/
interface Builder extends Objective.Builder {
@@ -113,11 +128,20 @@ public interface FilteringObjective extends Objective {
Builder deny();
/**
+ * Set meta information about this filtering condition set.
+ *
+ * @param treatment traffic treatment to use
+ * @return a filtering builder
+ */
+ Builder setMeta(TrafficTreatment treatment);
+
+ /**
* Assigns an application id.
*
* @param appId an application id
* @return a filtering builder
*/
+ @Override
Builder fromApp(ApplicationId appId);
/**
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
index 6efd3e79..9d942ee4 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
@@ -139,6 +139,20 @@ public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketE
watchGroup);
}
+ /**
+ * Creates all group bucket.
+ *
+ * @param treatment traffic treatment associated with group bucket
+ * @return all group bucket object
+ */
+ public static GroupBucket createAllGroupBucket(TrafficTreatment treatment) {
+ return new DefaultGroupBucket(GroupDescription.Type.ALL,
+ treatment,
+ (short) -1,
+ null,
+ null);
+ }
+
@Override
public GroupDescription.Type type() {
return this.type;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
index bd4219ad..c1467241 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
@@ -17,11 +17,15 @@ package org.onosproject.net.intent;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+
import org.onosproject.core.ApplicationId;
import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.constraint.LinkTypeConstraint;
import java.util.List;
@@ -33,6 +37,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Beta
public final class HostToHostIntent extends ConnectivityIntent {
+ static final LinkTypeConstraint NOT_OPTICAL = new LinkTypeConstraint(false, Link.Type.OPTICAL);
+
private final HostId one;
private final HostId two;
@@ -115,6 +121,15 @@ public final class HostToHostIntent extends ConnectivityIntent {
*/
public HostToHostIntent build() {
+ List<Constraint> theConstraints = constraints;
+ // If not-OPTICAL constraint hasn't been specified, add them
+ if (!constraints.contains(NOT_OPTICAL)) {
+ theConstraints = ImmutableList.<Constraint>builder()
+ .add(NOT_OPTICAL)
+ .addAll(constraints)
+ .build();
+ }
+
return new HostToHostIntent(
appId,
key,
@@ -122,7 +137,7 @@ public final class HostToHostIntent extends ConnectivityIntent {
two,
selector,
treatment,
- constraints,
+ theConstraints,
priority
);
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
index 18baafc8..0344acbf 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
@@ -28,7 +28,7 @@ import java.util.Objects;
*/
// TODO maybe pull this up to utils
@Beta
-public abstract class Key {
+public abstract class Key implements Comparable<Key> {
//TODO consider making this a HashCode object (worry about performance)
private final long hash;
@@ -117,6 +117,12 @@ public abstract class Key {
Objects.equals(this.appId, other.appId) &&
Objects.equals(this.key, other.key);
}
+
+ @Override
+ public int compareTo(Key o) {
+ StringKey sk = (StringKey) o;
+ return this.key.compareTo(sk.key);
+ }
}
private static final class LongKey extends Key {
@@ -157,6 +163,13 @@ public abstract class Key {
this.key == other.key &&
Objects.equals(this.appId, other.appId);
}
+
+ @Override
+ public int compareTo(Key o) {
+ Long myKey = key;
+ Long otherKey = ((LongKey) o).key;
+ return myKey.compareTo(otherKey);
+ }
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
index 43b8e4b1..20ccb55d 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
@@ -16,6 +16,8 @@
package org.onosproject.net.intent.constraint;
import com.google.common.annotations.Beta;
+
+import org.onlab.util.DataRateUnit;
import org.onosproject.net.Link;
import org.onosproject.net.resource.link.BandwidthResource;
import org.onosproject.net.resource.link.BandwidthResourceRequest;
@@ -32,7 +34,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Constraint that evaluates links based on available bandwidths.
*/
@Beta
-public class BandwidthConstraint extends BooleanConstraint {
+public final class BandwidthConstraint extends BooleanConstraint {
private final BandwidthResource bandwidth;
@@ -45,6 +47,17 @@ public class BandwidthConstraint extends BooleanConstraint {
this.bandwidth = checkNotNull(bandwidth, "Bandwidth cannot be null");
}
+ /**
+ * Creates a new bandwidth constraint.
+ *
+ * @param v required amount of bandwidth
+ * @param unit {@link DataRateUnit} of {@code v}
+ * @return {@link BandwidthConstraint} instance with given bandwidth requirement
+ */
+ public static BandwidthConstraint of(double v, DataRateUnit unit) {
+ return new BandwidthConstraint(BandwidthResource.of(v, unit));
+ }
+
// Constructor for serialization
private BandwidthConstraint() {
this.bandwidth = null;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
index 82d84743..ad684c8c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
@@ -153,6 +153,14 @@ public interface ResourceService {
Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer);
/**
+ * Returns resource paths that point available child resources under the specified resource path.
+ *
+ * @param parent parent resource path
+ * @return available resource paths under the specified resource path
+ */
+ Collection<ResourcePath> getAvailableResources(ResourcePath parent);
+
+ /**
* Returns the availability of the specified resource.
*
* @param resource resource to check the availability
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
index 5a034b4d..2cab9d4b 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
@@ -92,6 +92,14 @@ public interface ResourceStore {
Collection<ResourcePath> getResources(ResourceConsumer consumer);
/**
+ * Returns a collection of the child resources of the specified parent.
+ *
+ * @param parent parent of the resource to be returned
+ * @return a collection of the child resources of the specified resource
+ */
+ Collection<ResourcePath> getChildResources(ResourcePath parent);
+
+ /**
* Returns a collection of the resources which are children of the specified parent and
* whose type is the specified class.
*
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
index fe21e042..0bfb3795 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
@@ -16,7 +16,7 @@
package org.onosproject.net.resource.link;
import org.onlab.util.Bandwidth;
-
+import org.onlab.util.DataRateUnit;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -43,6 +43,17 @@ public final class BandwidthResource implements LinkResource {
}
/**
+ * Creates a new bandwidth resource.
+ *
+ * @param v amount of bandwidth to request
+ * @param unit {@link DataRateUnit} of {@code v}
+ * @return {@link BandwidthResource} instance with given bandwidth
+ */
+ public static BandwidthResource of(double v, DataRateUnit unit) {
+ return new BandwidthResource(Bandwidth.of(v, unit));
+ }
+
+ /**
* Returns bandwidth as a double value.
*
* @return bandwidth as a double value
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
index 5153aebf..f8e143a4 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
@@ -16,48 +16,47 @@
package org.onosproject.net.resource.link;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.Objects;
+import java.util.stream.Collectors;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableMap;
import org.onlab.util.Bandwidth;
import org.onosproject.net.Link;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.IntentId;
-import com.google.common.collect.ImmutableSet;
-
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.LambdaConstraint;
import org.onosproject.net.resource.ResourceRequest;
import org.onosproject.net.resource.ResourceType;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Implementation of {@link LinkResourceRequest}.
*/
public final class DefaultLinkResourceRequest implements LinkResourceRequest {
private final IntentId intentId;
- private final Collection<Link> links;
- private final Set<ResourceRequest> resources;
+ protected final Map<Link, Set<ResourceRequest>> requests;
/**
- * Creates a new link resource request with the given ID, links, and
- * resource requests.
+ * Creates a new link resource request with the specified Intent ID,
+ * and resource requests over links.
*
- * @param intentId intent ID related to this request
- * @param links a set of links for the request
- * @param resources a set of resources to be requested
+ * @param intentId intent ID associated with this request
+ * @param requests resource requests over links
*/
- private DefaultLinkResourceRequest(IntentId intentId,
- Collection<Link> links,
- Set<ResourceRequest> resources) {
- this.intentId = intentId;
- this.links = ImmutableSet.copyOf(links);
- this.resources = ImmutableSet.copyOf(resources);
+ private DefaultLinkResourceRequest(IntentId intentId, Map<Link, Set<ResourceRequest>> requests) {
+ this.intentId = checkNotNull(intentId);
+ this.requests = checkNotNull(ImmutableMap.copyOf(requests));
}
-
@Override
public ResourceType type() {
return null;
@@ -70,12 +69,19 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
@Override
public Collection<Link> links() {
- return links;
+ return requests.keySet();
}
@Override
public Set<ResourceRequest> resources() {
- return resources;
+ return requests.values().stream()
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<ResourceRequest> resources(Link link) {
+ return requests.get(link);
}
/**
@@ -95,8 +101,7 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
public static final class Builder implements LinkResourceRequest.Builder {
private IntentId intentId;
- private Collection<Link> links;
- private Set<ResourceRequest> resources;
+ private Map<Link, Set<ResourceRequest>> requests;
/**
* Creates a new link resource request.
@@ -106,18 +111,33 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
private Builder(IntentId intentId, Collection<Link> links) {
this.intentId = intentId;
- this.links = links;
- this.resources = new HashSet<>();
+ this.requests = new HashMap<>();
+ for (Link link : links) {
+ requests.put(link, new HashSet<>());
+ }
}
/**
* Adds lambda request.
*
* @return self
+ * @deprecated in Emu Release
*/
+ @Deprecated
@Override
public Builder addLambdaRequest() {
- resources.add(new LambdaResourceRequest());
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new LambdaResourceRequest());
+ }
+ return this;
+ }
+
+ @Beta
+ @Override
+ public LinkResourceRequest.Builder addLambdaRequest(LambdaResource lambda) {
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new LambdaResourceRequest(lambda));
+ }
return this;
}
@@ -125,10 +145,36 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
* Adds Mpls request.
*
* @return self
+ * @deprecated in Emu Release
*/
+ @Deprecated
@Override
public Builder addMplsRequest() {
- resources.add(new MplsLabelResourceRequest());
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new MplsLabelResourceRequest());
+ }
+ return this;
+ }
+
+ @Beta
+ @Override
+ public Builder addMplsRequest(MplsLabel label) {
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new MplsLabelResourceRequest(label));
+ }
+ return this;
+ }
+
+ @Beta
+ @Override
+ public LinkResourceRequest.Builder addMplsRequest(Map<Link, MplsLabel> labels) {
+ for (Link link : labels.keySet()) {
+ if (!requests.containsKey(link)) {
+ requests.put(link, new HashSet<>());
+ }
+ requests.get(link).add(new MplsLabelResourceRequest(labels.get(link)));
+ }
+
return this;
}
@@ -140,7 +186,9 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
@Override
public Builder addBandwidthRequest(double bandwidth) {
- resources.add(new BandwidthResourceRequest(new BandwidthResource(Bandwidth.bps(bandwidth))));
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new BandwidthResourceRequest(new BandwidthResource(Bandwidth.bps(bandwidth))));
+ }
return this;
}
@@ -162,13 +210,13 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
@Override
public LinkResourceRequest build() {
- return new DefaultLinkResourceRequest(intentId, links, resources);
+ return new DefaultLinkResourceRequest(intentId, requests);
}
}
@Override
public int hashCode() {
- return Objects.hash(intentId, links);
+ return Objects.hash(intentId, links());
}
@Override
@@ -181,6 +229,6 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
}
final DefaultLinkResourceRequest other = (DefaultLinkResourceRequest) obj;
return Objects.equals(this.intentId, other.intentId)
- && Objects.equals(this.links, other.links);
+ && Objects.equals(this.links(), other.links());
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
index b0391f5a..d264d5e5 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
@@ -15,15 +15,50 @@
*/
package org.onosproject.net.resource.link;
+import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import org.onosproject.net.resource.ResourceRequest;
import org.onosproject.net.resource.ResourceType;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Representation of a request for lambda resource.
*/
public class LambdaResourceRequest implements ResourceRequest {
+ private final LambdaResource lambda;
+
+ /**
+ * Constructs a request specifying the given lambda.
+ *
+ * @param lambda lambda to be requested
+ */
+ @Beta
+ public LambdaResourceRequest(LambdaResource lambda) {
+ this.lambda = checkNotNull(lambda);
+ }
+
+ /**
+ * Constructs a request asking an arbitrary available lambda.
+ *
+ * @deprecated in Emu Release
+ */
+ @Deprecated
+ public LambdaResourceRequest() {
+ this.lambda = null;
+ }
+
+ /**
+ * Returns the lambda this request expects.
+ *
+ * @return the lambda this request expects
+ */
+ @Beta
+ public LambdaResource lambda() {
+ return lambda;
+ }
+
@Override
public ResourceType type() {
return ResourceType.LAMBDA;
@@ -32,6 +67,7 @@ public class LambdaResourceRequest implements ResourceRequest {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
.toString();
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
index 8023a92e..37622e79 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
@@ -16,8 +16,10 @@
package org.onosproject.net.resource.link;
import java.util.Collection;
+import java.util.Map;
import java.util.Set;
+import com.google.common.annotations.Beta;
import org.onosproject.net.Link;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.IntentId;
@@ -50,22 +52,62 @@ public interface LinkResourceRequest extends ResourceRequest {
Set<ResourceRequest> resources();
/**
+ * Returns the set of resource request against the specified link.
+ *
+ * @param link link whose associated resource request is to be returned
+ * @return set of resource request against the specified link
+ */
+ @Beta
+ Set<ResourceRequest> resources(Link link);
+
+ /**
* Builder of link resource request.
*/
interface Builder {
- /**
+ /**
* Adds lambda request.
*
* @return self
+ * @deprecated in Emu Release
*/
+ @Deprecated
Builder addLambdaRequest();
/**
- * Adds MPLS request.
- *
- * @return self
- */
- Builder addMplsRequest();
+ * Adds lambda request.
+ *
+ * @param lambda lambda to be requested
+ * @return self
+ */
+ @Beta
+ Builder addLambdaRequest(LambdaResource lambda);
+
+ /**
+ * Adds MPLS request.
+ *
+ * @return self
+ * @deprecated in Emu Release
+ */
+ @Deprecated
+ Builder addMplsRequest();
+
+ /**
+ * Adds MPLS request.
+ *
+ * @param label MPLS label to be requested
+ * @return self
+ */
+ @Beta
+ Builder addMplsRequest(MplsLabel label);
+
+ /**
+ * Adds MPLS request against the specified links.
+ *
+ * @param labels MPLS labels to be requested against links
+ * @return self
+ */
+ @Beta
+ Builder addMplsRequest(Map<Link, MplsLabel> labels);
/**
* Adds bandwidth request with bandwidth value.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
index 6dc04dfc..71ea7e1a 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
@@ -22,7 +22,10 @@ import org.onosproject.net.resource.ResourceRequest;
/**
* Service for providing link resource allocation.
+ *
+ * @deprecated in Emu Release
*/
+@Deprecated
public interface LinkResourceService
extends ListenerService<LinkResourceEvent, LinkResourceListener> {
@@ -31,14 +34,18 @@ public interface LinkResourceService
*
* @param req resources to be allocated
* @return allocated resources
+ * @deprecated in Emu Release
*/
+ @Deprecated
LinkResourceAllocations requestResources(LinkResourceRequest req);
/**
* Releases resources.
*
* @param allocations resources to be released
+ * @deprecated in Emu Release
*/
+ @Deprecated
void releaseResources(LinkResourceAllocations allocations);
/**
@@ -47,7 +54,9 @@ public interface LinkResourceService
* @param req updated resource request
* @param oldAllocations old resource allocations
* @return new resource allocations
+ * @deprecated in Emu Release
*/
+ @Deprecated
LinkResourceAllocations updateResources(LinkResourceRequest req,
LinkResourceAllocations oldAllocations);
@@ -55,7 +64,9 @@ public interface LinkResourceService
* Returns all allocated resources.
*
* @return allocated resources
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<LinkResourceAllocations> getAllocations();
/**
@@ -63,7 +74,9 @@ public interface LinkResourceService
*
* @param link a target link
* @return allocated resources
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<LinkResourceAllocations> getAllocations(Link link);
/**
@@ -71,7 +84,9 @@ public interface LinkResourceService
*
* @param intentId the target Intent's id
* @return allocated resources for Intent
+ * @deprecated in Emu Release
*/
+ @Deprecated
LinkResourceAllocations getAllocations(IntentId intentId);
/**
@@ -79,7 +94,9 @@ public interface LinkResourceService
*
* @param link a target link
* @return available resources for the target link
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<ResourceRequest> getAvailableResources(Link link);
/**
@@ -88,7 +105,9 @@ public interface LinkResourceService
* @param link a target link
* @param allocations allocations to be included as available
* @return available resources for the target link
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<ResourceRequest> getAvailableResources(Link link,
LinkResourceAllocations allocations);
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
index 0a03f450..01a048b7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
@@ -15,15 +15,50 @@
*/
package org.onosproject.net.resource.link;
+import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import org.onosproject.net.resource.ResourceRequest;
import org.onosproject.net.resource.ResourceType;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Representation of a request for lambda resource.
*/
public class MplsLabelResourceRequest implements ResourceRequest {
+ private final MplsLabel mplsLabel;
+
+ /**
+ * Constructs a request specifying the given MPLS label.
+ *
+ * @param mplsLabel MPLS label to be requested
+ */
+ @Beta
+ public MplsLabelResourceRequest(MplsLabel mplsLabel) {
+ this.mplsLabel = checkNotNull(mplsLabel);
+ }
+
+ /**
+ * Constructs a request asking an arbitrary available MPLS label.
+ *
+ * @deprecated in Emu Release
+ */
+ @Deprecated
+ public MplsLabelResourceRequest() {
+ this.mplsLabel = null;
+ }
+
+ /**
+ * Returns the MPLS label this request expects.
+ *
+ * @return the MPLS label this request expects
+ */
+ @Beta
+ public MplsLabel mplsLabel() {
+ return mplsLabel;
+ }
+
@Override
public ResourceType type() {
return ResourceType.MPLS_LABEL;
@@ -32,6 +67,7 @@ public class MplsLabelResourceRequest implements ResourceRequest {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
+ .add("mplsLabel", mplsLabel)
.toString();
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java
new file mode 100644
index 00000000..09065dec
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.persistence;
+
+/**
+ * Service that allows for the creation of local disk backed map for instance specific values that persist across
+ * restarts. Empty maps and sets are deleted on shutdown.
+ */
+public interface PersistenceService {
+ /**
+ * A builder for the creation of local persistent maps backed by disk.
+ *
+ * @param <K> the type of keys in this map
+ * @param <V> the type of values in this map
+ * @return a persistent map builder
+ */
+ <K, V> PersistentMapBuilder<K, V> persistentMapBuilder();
+
+ /**
+ * A builder for the creation of local persistent sets backed by disk.
+ *
+ * @param <E> the type of the elements
+ * @return a persistent set builder
+ */
+ <E> PersistentSetBuilder<E> persistentSetBuilder();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java
new file mode 100644
index 00000000..c3c855e1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * 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.persistence;
+
+
+import org.onosproject.store.service.Serializer;
+
+import java.util.Map;
+
+/**
+ * The interface for a persistent map builder for use with mapDB.
+ */
+public interface PersistentMapBuilder<K, V> {
+
+ /**
+ * Sets the name of this map.
+ * @param name the string name of this map
+ * @return a persistent map builder with the name option now set
+ */
+ PersistentMapBuilder<K, V> withName(String name);
+
+ /**
+ * Sets the key serializer to be used to serialize this map, this is a required parameter.
+ * @param serializer the serializer to be used for keys
+ * @return a persistent map builder with the key serializer set
+ */
+ PersistentMapBuilder<K, V> withSerializer(Serializer serializer);
+
+ /**
+ * Validates the map settings and then builds this map in the database. Throws an exception if invalid settings
+ * are found.
+ * @return The map that was created
+ */
+ Map<K, V> build();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java
new file mode 100644
index 00000000..851872cf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * 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.persistence;
+
+import org.onosproject.store.service.Serializer;
+
+import java.util.Set;
+
+/**
+ * The default interface for the persistent set builder for use with mapDB.
+ */
+public interface PersistentSetBuilder<E> {
+
+ /**
+ * Sets the name of this set.
+ * @param name the string name of this set
+ * @return a persistent set builder with the name option now set
+ */
+ PersistentSetBuilder<E> withName(String name);
+
+ /**
+ * Sets the serializer to be used to serialize this set, this is a required parameter.
+ * @param serializer the serializer to be used
+ * @return a persistent set builder with the serializer set
+ */
+ PersistentSetBuilder<E> withSerializer(Serializer serializer);
+
+ /**
+ * Validates the set settings and then builds this map in the database. Throws an exception if invalid settings
+ * are found.
+ * @return The set that was created
+ */
+ Set<E> build();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java
new file mode 100644
index 00000000..6e11a5e1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Persistence service and builders.
+ */
+package org.onosproject.persistence;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
index 94942e20..ef972536 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
@@ -56,9 +56,9 @@ public interface TransactionContext {
* Commits a transaction that was previously started thereby making its changes permanent
* and externally visible.
*
- * @throws TransactionException if transaction fails to commit
+ * @return true if this transaction succeeded, otherwise false.
*/
- void commit();
+ boolean commit();
/**
* Aborts any changes made in this transaction context and discarding all locally cached updates.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
index e0d7d239..88796de7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
@@ -16,6 +16,8 @@
package org.onosproject.ui;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
import org.onosproject.ui.topo.PropertyPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -105,8 +107,9 @@ public class UiTopoOverlay {
* This default implementation does nothing.
*
* @param pp property panel model of summary data
+ * @param deviceId device id
*/
- public void modifyDeviceDetails(PropertyPanel pp) {
+ public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) {
}
/**
@@ -115,7 +118,8 @@ public class UiTopoOverlay {
* This default implementation does nothing.
*
* @param pp property panel model of summary data
+ * @param hostId host id
*/
- public void modifyHostDetails(PropertyPanel pp) {
+ public void modifyHostDetails(PropertyPanel pp, HostId hostId) {
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
index 0e1c248b..f7947a75 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
@@ -27,6 +27,7 @@ public final class AppIdFormatter extends AbstractCellFormatter {
// non-instantiable
private AppIdFormatter() { }
+ // NOTE: do not change this format; we parse it on the client side.
@Override
protected String nonNullFormat(Object value) {
ApplicationId appId = (ApplicationId) value;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
index 7b517111..4edb6712 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
@@ -40,7 +40,7 @@ public final class NodeBadge {
return "{" + code + "}";
}
- /** Returns the status code in string form. */
+ /* Returns the status code in string form. */
public String code() {
return code;
}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java
index 3f7650e4..c3a95473 100644
--- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java
@@ -16,15 +16,18 @@
package org.onosproject.net.intent;
import org.junit.Test;
+import org.onlab.util.DataRateUnit;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.HostId;
import org.onosproject.net.flow.TrafficSelector;
-
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import com.google.common.collect.ImmutableList;
import com.google.common.testing.EqualsTester;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import static org.onosproject.net.NetTestTools.hid;
@@ -102,6 +105,55 @@ public class HostToHostIntentTest extends IntentTest {
.testEquals();
}
+ @Test
+ public void testImplicitConstraintsAreAdded() {
+ final Constraint other = BandwidthConstraint.of(1, DataRateUnit.GBPS);
+ final HostToHostIntent intent = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(ImmutableList.of(other))
+ .build();
+
+ assertThat(intent.constraints(), hasItem(HostToHostIntent.NOT_OPTICAL));
+ }
+
+ @Test
+ public void testImplicitConstraints() {
+ final HostToHostIntent implicit = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .build();
+ final HostToHostIntent empty = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(ImmutableList.of())
+ .build();
+ final HostToHostIntent exact = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(ImmutableList.of(HostToHostIntent.NOT_OPTICAL))
+ .build();
+
+ new EqualsTester()
+ .addEqualityGroup(implicit.constraints(),
+ empty.constraints(),
+ exact.constraints())
+ .testEquals();
+
+ }
+
@Override
protected Intent createOne() {
return HostToHostIntent.builder()
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java
new file mode 100644
index 00000000..592cd983
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.packet;
+
+import org.junit.Test;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for the DefaultPacketRequest class.
+ */
+public class DefaultPacketRequestTest {
+
+ private final TrafficSelector selector = DefaultTrafficSelector
+ .builder()
+ .matchIcmpCode((byte) 1)
+ .build();
+
+ private final DefaultPacketRequest packetRequest1 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.CONTROL,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest sameAsacketRequest1 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.CONTROL,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest packetRequest2 =
+ new DefaultPacketRequest(selector,
+ PacketPriority.CONTROL,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest packetRequest3 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.REACTIVE,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest packetRequest4 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.CONTROL,
+ new DefaultApplicationId(1, "foo"));
+
+ /**
+ * Tests the operation of the equals(), toAstring() and hashCode() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(packetRequest1, sameAsacketRequest1)
+ .addEqualityGroup(packetRequest2)
+ .addEqualityGroup(packetRequest3)
+ .addEqualityGroup(packetRequest4)
+ .testEquals();
+ }
+
+ /**
+ * Tests that building and fetching from a DefaultPacketRequest is correct.
+ */
+ @Test
+ public void testConstruction() {
+ assertThat(packetRequest1.priority(), is(PacketPriority.CONTROL));
+ assertThat(packetRequest1.priority().priorityValue(),
+ is(PacketPriority.CONTROL.priorityValue()));
+ assertThat(packetRequest1.selector(), is(DefaultTrafficSelector.emptySelector()));
+ assertThat(packetRequest1.appId(), is(NetTestTools.APP_ID));
+ }
+
+ /**
+ * Checks that the DefaultPacketRequest class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultPacketRequest.class);
+ }
+}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java
new file mode 100644
index 00000000..f0d45f0c
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Unit tests for PacketEvent class.
+ */
+public class PacketEventTest {
+
+ OutboundPacket packet;
+
+ @Test
+ public void testConstruction1() {
+ long time = System.currentTimeMillis();
+ PacketEvent event = new PacketEvent(PacketEvent.Type.EMIT, packet);
+
+ assertThat(event.type(), is(PacketEvent.Type.EMIT));
+ assertThat(event.subject(), is(packet));
+ assertThat(event.time(), greaterThanOrEqualTo(time));
+ }
+
+ @Test
+ public void testConstruction2() {
+ long time = 12345678;
+ PacketEvent event = new PacketEvent(PacketEvent.Type.EMIT, packet, time);
+
+ assertThat(event.type(), is(PacketEvent.Type.EMIT));
+ assertThat(event.subject(), is(packet));
+ assertThat(event.time(), is(time));
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java
new file mode 100644
index 00000000..7b2ef541
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThan;
+
+/**
+ * Unit tests for static APIs in the packet processor class.
+ */
+public class PacketProcessorTest {
+
+ /**
+ * Tests a priority in the advisor range.
+ */
+ @Test
+ public void testAdvisorPriorities() {
+ int advisorPriority = PacketProcessor.advisor(3);
+ assertThat(advisorPriority, lessThan(PacketProcessor.ADVISOR_MAX));
+ assertThat(advisorPriority, greaterThanOrEqualTo(0));
+ }
+
+ /**
+ * Tests a priority in the director range.
+ */
+ @Test
+ public void testDirectorPriorities() {
+ int directorPriority = PacketProcessor.director(3);
+ assertThat(directorPriority, lessThan(PacketProcessor.DIRECTOR_MAX));
+ assertThat(directorPriority, greaterThanOrEqualTo(PacketProcessor.ADVISOR_MAX));
+ }
+
+ /**
+ * Tests a priority in the observer range.
+ */
+ @Test
+ public void testObserverPriorities() {
+ int observerPriority = PacketProcessor.observer(3);
+ assertThat(observerPriority, lessThan(PacketProcessor.OBSERVER_MAX));
+ assertThat(observerPriority, greaterThanOrEqualTo(PacketProcessor.DIRECTOR_MAX));
+ }
+
+}
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
index 4e0f2bd9..69c5e791 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.codec.impl;
+import static org.onlab.util.Tools.nullIsIllegal;
+
import java.util.HashMap;
import java.util.Map;
@@ -24,9 +26,13 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalId;
+import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
@@ -34,8 +40,6 @@ import org.onosproject.net.flow.criteria.Criterion;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import static org.onlab.util.Tools.nullIsIllegal;
-
/**
* Decode portion of the criterion codec.
*/
@@ -95,6 +99,8 @@ public final class DecodeCriterionCodecHelper {
decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder());
decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder());
decoderMap.put(Criterion.Type.TUNNEL_ID.name(), new TunnelIdDecoder());
+ decoderMap.put(Criterion.Type.ODU_SIGID.name(), new OduSigIdDecoder());
+ decoderMap.put(Criterion.Type.ODU_SIGTYPE.name(), new OduSigTypeDecoder());
}
private class EthTypeDecoder implements CriterionDecoder {
@@ -415,7 +421,9 @@ public final class DecodeCriterionCodecHelper {
private class OchSigTypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
- return null;
+ OchSignalType ochSignalType = OchSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_TYPE),
+ CriterionCodec.OCH_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
+ return Criteria.matchOchSignalType(ochSignalType);
}
}
@@ -428,6 +436,34 @@ public final class DecodeCriterionCodecHelper {
}
}
+ private class OduSigIdDecoder implements CriterionDecoder {
+ @Override
+ public Criterion decodeCriterion(ObjectNode json) {
+ JsonNode oduSignalId = nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_ID),
+ CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE);
+
+ int tributaryPortNumber = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_PORT_NUMBER),
+ CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE).asInt();
+ int tributarySlotLen = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_LEN),
+ CriterionCodec.TRIBUTARY_SLOT_LEN + MISSING_MEMBER_MESSAGE).asInt();
+ byte[] tributarySlotBitmap = HexString.fromHexString(
+ nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP),
+ CriterionCodec.TRIBUTARY_SLOT_BITMAP + MISSING_MEMBER_MESSAGE).asText());
+
+ return Criteria.matchOduSignalId(
+ OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap));
+ }
+ }
+
+ private class OduSigTypeDecoder implements CriterionDecoder {
+ @Override
+ public Criterion decodeCriterion(ObjectNode json) {
+ OduSignalType oduSignalType = OduSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_TYPE),
+ CriterionCodec.ODU_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
+ return Criteria.matchOduSignalType(oduSignalType);
+ }
+ }
+
/**
* Decodes the JSON into a criterion object.
*
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
index 6a97a076..14555b3d 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
@@ -15,26 +15,29 @@
*/
package org.onosproject.codec.impl;
+import static org.onlab.util.Tools.nullIsIllegal;
+
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.PortNumber;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
-import static org.onlab.util.Tools.nullIsIllegal;
+import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Decoding portion of the instruction codec.
@@ -174,6 +177,30 @@ public final class DecodeInstructionCodecHelper {
}
/**
+ * Decodes a Layer 1 instruction.
+ *
+ * @return instruction object decoded from the JSON
+ * @throws IllegalArgumentException if the JSON is invalid
+ */
+ private Instruction decodeL1() {
+ String subType = json.get(InstructionCodec.SUBTYPE).asText();
+ if (subType.equals(L1ModificationInstruction.L1SubType.ODU_SIGID.name())) {
+ int tributaryPortNumber = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_PORT_NUMBER),
+ InstructionCodec.TRIBUTARY_PORT_NUMBER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
+ int tributarySlotLen = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_LEN),
+ InstructionCodec.TRIBUTARY_SLOT_LEN + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
+ byte[] tributarySlotBitmap = null;
+ tributarySlotBitmap = HexString.fromHexString(
+ nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_BITMAP),
+ InstructionCodec.TRIBUTARY_SLOT_BITMAP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
+ return Instructions.modL1OduSignalId(OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen,
+ tributarySlotBitmap));
+ }
+ throw new IllegalArgumentException("L1 Instruction subtype "
+ + subType + " is not supported");
+ }
+
+ /**
* Decodes a Layer 4 instruction.
*
* @return instruction object decoded from the JSON
@@ -221,6 +248,8 @@ public final class DecodeInstructionCodecHelper {
return Instructions.createDrop();
} else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
return decodeL0();
+ } else if (type.equals(Instruction.Type.L1MODIFICATION.name())) {
+ return decodeL1();
} else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
return decodeL2();
} else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
index f7af736e..8fc6bbcf 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
@@ -17,8 +17,10 @@ package org.onosproject.codec.impl;
import java.util.EnumMap;
+import org.onlab.util.HexString;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
@@ -370,12 +372,18 @@ public final class EncodeCriterionCodecHelper {
private static class FormatOduSignalId implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
- final OduSignalIdCriterion oduSignalIdCriterion =
- (OduSignalIdCriterion) criterion;
- return root.put(CriterionCodec.ODU_SIGNAL_ID, oduSignalIdCriterion.oduSignalId().toString());
+ OduSignalId oduSignalId = ((OduSignalIdCriterion) criterion).oduSignalId();
+ ObjectNode child = root.putObject(CriterionCodec.ODU_SIGNAL_ID);
+
+ child.put(CriterionCodec.TRIBUTARY_PORT_NUMBER, oduSignalId.tributaryPortNumber());
+ child.put(CriterionCodec.TRIBUTARY_SLOT_LEN, oduSignalId.tributarySlotLength());
+ child.put(CriterionCodec.TRIBUTARY_SLOT_BITMAP, HexString.toHexString(oduSignalId.tributarySlotBitmap()));
+
+ return root;
}
}
+
private static class FormatOduSignalType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
index d12e4ad8..2ec301db 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
@@ -15,11 +15,14 @@
*/
package org.onosproject.codec.impl;
+import org.onlab.util.HexString;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
@@ -81,6 +84,36 @@ public final class EncodeInstructionCodecHelper {
}
/**
+ * Encode an L1 modification instruction.
+ *
+ * @param result json node that the instruction attributes are added to
+ * @param instruction The L1 instruction
+ * @param context context of the request
+ */
+ private void encodeL1(ObjectNode result) {
+ L1ModificationInstruction instruction =
+ (L1ModificationInstruction) this.instruction;
+ result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
+
+ switch (instruction.subtype()) {
+ case ODU_SIGID:
+ final L1ModificationInstruction.ModOduSignalIdInstruction oduSignalIdInstruction =
+ (L1ModificationInstruction.ModOduSignalIdInstruction) instruction;
+ OduSignalId oduSignalId = oduSignalIdInstruction.oduSignalId();
+
+ ObjectNode child = result.putObject("oduSignalId");
+
+ child.put(InstructionCodec.TRIBUTARY_PORT_NUMBER, oduSignalId.tributaryPortNumber());
+ child.put(InstructionCodec.TRIBUTARY_SLOT_LEN, oduSignalId.tributarySlotLength());
+ child.put(InstructionCodec.TRIBUTARY_SLOT_BITMAP, HexString.toHexString(oduSignalId.tributarySlotBitmap()));
+ break;
+ default:
+ log.info("Cannot convert L1 subtype of {}", instruction.subtype());
+ break;
+ }
+ }
+
+ /**
* Encode an L2 modification instruction.
*
* @param result json node that the instruction attributes are added to
@@ -222,6 +255,10 @@ public final class EncodeInstructionCodecHelper {
encodeL0(result);
break;
+ case L1MODIFICATION:
+ encodeL1(result);
+ break;
+
case L2MODIFICATION:
encodeL2(result);
break;
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
index f4d5008a..d7307ad3 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
@@ -50,6 +50,9 @@ public final class InstructionCodec extends JsonCodec<Instruction> {
protected static final String TUNNEL_ID = "tunnelId";
protected static final String TCP_PORT = "tcpPort";
protected static final String UDP_PORT = "udpPort";
+ protected static final String TRIBUTARY_PORT_NUMBER = "tributaryPortNumber";
+ protected static final String TRIBUTARY_SLOT_LEN = "tributarySlotLength";
+ protected static final String TRIBUTARY_SLOT_BITMAP = "tributarySlotBitmap";
protected static final String MISSING_MEMBER_MESSAGE =
" member is required in Instruction";
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
index 54e1146b..86374f81 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
@@ -31,6 +31,8 @@ import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalId;
+import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
@@ -54,6 +56,10 @@ public class CriterionCodecTest {
final IpPrefix ipPrefix6 = IpPrefix.valueOf("fe80::/64");
final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
final TpPort tpPort = TpPort.tpPort(40000);
+ final int tributaryPortNumber = 11;
+ final int tributarySlotLen = 80;
+ final byte[] tributarySlotBitmap = new byte[] {1, 2, 3, 4, 2, 3, 4, 2, 3, 4};
+
/**
* Sets up for each test. Creates a context and fetches the criterion
@@ -427,4 +433,31 @@ public class CriterionCodecTest {
ObjectNode result = criterionCodec.encode(criterion, context);
assertThat(result, matchesCriterion(criterion));
}
+
+ /**
+ * Tests Odu Signal ID criterion.
+ */
+ @Test
+ public void matchOduSignalIdTest() {
+
+ OduSignalId oduSignalId = OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap);
+
+ Criterion criterion = Criteria.matchOduSignalId(oduSignalId);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests Odu Signal Type criterion.
+ */
+ @Test
+ public void matchOduSignalTypeTest() {
+
+ OduSignalType signalType = OduSignalType.ODU2;
+
+ Criterion criterion = Criteria.matchOduSignalType(signalType);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
index bb3acad5..b00632c3 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
@@ -15,13 +15,14 @@
*/
package org.onosproject.codec.impl;
-import com.google.common.base.Joiner;
+import java.util.Objects;
+
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.util.HexString;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.criteria.Criterion;
-
-import com.fasterxml.jackson.databind.JsonNode;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
@@ -40,6 +41,8 @@ import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -47,7 +50,8 @@ import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
-import java.util.Objects;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.base.Joiner;
/**
* Hamcrest matcher for criterion objects.
@@ -496,6 +500,44 @@ public final class CriterionJsonMatcher extends
return true;
}
+ /**
+ * Matches an ODU signal ID criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(OduSignalIdCriterion criterion) {
+ final OduSignalId oduSignal = criterion.oduSignalId();
+ final JsonNode jsonOduSignal = jsonCriterion.get(CriterionCodec.ODU_SIGNAL_ID);
+ int jsonTpn = jsonOduSignal.get(CriterionCodec.TRIBUTARY_PORT_NUMBER).intValue();
+ int jsonTsLen = jsonOduSignal.get(CriterionCodec.TRIBUTARY_SLOT_LEN).intValue();
+ byte[] jsonTributaryBitMap = HexString.fromHexString(
+ jsonOduSignal.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP).asText());
+ OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, jsonTributaryBitMap);
+ if (!oduSignal.equals(jsonOduSignalId)) {
+ description.appendText("oduSignalId was " + criterion);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an ODU signal Type criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(OduSignalTypeCriterion criterion) {
+ final String signalType = criterion.signalType().name();
+ final String jsonOduSignalType = jsonCriterion.get("oduSignalType").textValue();
+ if (!signalType.equals(jsonOduSignalType)) {
+ description.appendText("signalType was " + signalType);
+ return false;
+ }
+ return true;
+ }
+
+
@Override
public boolean matchesSafely(JsonNode jsonCriterion,
Description description) {
@@ -594,6 +636,12 @@ public final class CriterionJsonMatcher extends
case OCH_SIGTYPE:
return matchCriterion((OchSignalTypeCriterion) criterion);
+ case ODU_SIGID:
+ return matchCriterion((OduSignalIdCriterion) criterion);
+
+ case ODU_SIGTYPE:
+ return matchCriterion((OduSignalTypeCriterion) criterion);
+
default:
// Don't know how to format this type
description.appendText("unknown criterion type " +
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
index 6c88ac1e..f6a92131 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
@@ -15,6 +15,15 @@
*/
package org.onosproject.codec.impl;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
import java.io.IOException;
import java.io.InputStream;
import java.util.SortedMap;
@@ -35,6 +44,8 @@ import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.Criterion;
@@ -55,6 +66,9 @@ import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -62,9 +76,6 @@ import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
@@ -72,14 +83,8 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.NetTestTools.APP_ID;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Flow rule codec unit tests.
@@ -382,7 +387,7 @@ public class FlowRuleCodecTest {
checkCommonData(rule);
- assertThat(rule.selector().criteria().size(), is(33));
+ assertThat(rule.selector().criteria().size(), is(36));
rule.selector().criteria()
.stream()
@@ -518,6 +523,25 @@ public class FlowRuleCodecTest {
criterion = getCriterion(Criterion.Type.TUNNEL_ID);
assertThat(((TunnelIdCriterion) criterion).tunnelId(),
is(100L));
+
+ criterion = getCriterion(Criterion.Type.OCH_SIGTYPE);
+ assertThat(((OchSignalTypeCriterion) criterion).signalType(),
+ is(OchSignalType.FIXED_GRID));
+
+ criterion = getCriterion(Criterion.Type.ODU_SIGTYPE);
+ assertThat(((OduSignalTypeCriterion) criterion).signalType(),
+ is(OduSignalType.ODU4));
+
+
+ criterion = getCriterion(Criterion.Type.ODU_SIGID);
+ assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributaryPortNumber(),
+ is(1));
+
+ assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributarySlotLength(),
+ is(80));
+
+ assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributarySlotBitmap(),
+ is(new byte [] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}));
}
/**
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
index bafbc0f1..f7b0261e 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
@@ -15,6 +15,10 @@
*/
package org.onosproject.codec.impl;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
+
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
@@ -28,26 +32,23 @@ import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Lambda;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
-
/**
* Unit tests for Instruction codec.
*/
public class InstructionCodecTest {
CodecContext context;
JsonCodec<Instruction> instructionCodec;
-
/**
* Sets up for each test. Creates a context and fetches the instruction
* codec.
@@ -122,6 +123,20 @@ public class InstructionCodecTest {
}
/**
+ * Tests the encoding of mod ODU signal ID instructions.
+ */
+ @Test
+ public void modOduSignalIdInstructionTest() {
+ OduSignalId oduSignalId = OduSignalId.oduSignalId(1, 8, new byte [] {8, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+ L1ModificationInstruction.ModOduSignalIdInstruction instruction =
+ (L1ModificationInstruction.ModOduSignalIdInstruction)
+ Instructions.modL1OduSignalId(oduSignalId);
+ ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
* Tests the encoding of mod ether instructions.
*/
@Test
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
index c3cdca0f..9ffb3c3a 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
@@ -17,15 +17,25 @@ package org.onosproject.codec.impl;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.util.HexString;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions.DropInstruction;
+import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
import com.fasterxml.jackson.databind.JsonNode;
-import static org.onosproject.net.flow.instructions.Instructions.*;
-import static org.onosproject.net.flow.instructions.L0ModificationInstruction.*;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.*;
-import static org.onosproject.net.flow.instructions.L3ModificationInstruction.*;
-
/**
* Hamcrest matcher for instructions.
*/
@@ -133,7 +143,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
}
/**
- * Matches teh contents of a mod OCh singal instruction.
+ * Matches the contents of a mod OCh singal instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
@@ -184,6 +194,40 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
}
/**
+ * Matches the contents of a mod ODU singal Id instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents matches, false otherwise
+ */
+ private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
+ Description description) {
+ ModOduSignalIdInstruction instructionToMatch =
+ (ModOduSignalIdInstruction) instruction;
+ String jsonSubType = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
+ description.appendText("subtype was " + jsonSubType);
+ return false;
+ }
+ String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+ final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
+ int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
+ int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
+ byte [] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
+ OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
+ if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
+ description.appendText("oduSignalId was " + instructionToMatch);
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
* Matches the contents of a mod Ethernet instruction.
*
* @param instructionJson JSON instruction to match
@@ -416,6 +460,8 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
description);
} else if (instruction instanceof ModMplsLabelInstruction) {
return matchModMplsLabelInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModOduSignalIdInstruction) {
+ return matchModOduSingalIdInstruction(jsonInstruction, description);
} else if (instruction instanceof NoActionInstruction) {
return true;
}
diff --git a/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json b/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
index 1a96e92f..ccb2e161 100644
--- a/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
+++ b/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
@@ -38,7 +38,10 @@
{"type":"MPLS_LABEL", "label":123},
{"type":"IPV6_EXTHDR", "exthdrFlags":99},
{"type":"OCH_SIGID", "lambda":122},
- {"type":"TUNNEL_ID", "tunnelId":100}
+ {"type":"TUNNEL_ID", "tunnelId":100},
+ {"type":"OCH_SIGTYPE", "ochSignalType":"FIXED_GRID"},
+ {"type":"ODU_SIGTYPE", "oduSignalType":"ODU4"},
+ {"type":"ODU_SIGID", "oduSignalId" : {"tributaryPortNumber":1, "tributarySlotLen":80, "tributarySlotBitmap":"01:01:01:01:01:01:01:01:01:01"}}
]
}
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
index 04d1dfdf..7ddac0ce 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
@@ -25,17 +25,26 @@ import org.apache.karaf.system.SystemService;
import org.joda.time.DateTime;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterAdminService;
-import org.onosproject.cluster.ClusterDefinitionService;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterEventListener;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ClusterStore;
import org.onosproject.cluster.ClusterStoreDelegate;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.Partition;
import org.onosproject.event.AbstractListenerManager;
import org.slf4j.Logger;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
@@ -44,8 +53,6 @@ import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
-
-
/**
* Implementation of the cluster service.
*/
@@ -61,7 +68,7 @@ public class ClusterManager
private ClusterStoreDelegate delegate = new InternalStoreDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterStore store;
@@ -73,8 +80,9 @@ public class ClusterManager
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(ClusterEvent.class, listenerRegistry);
- clusterDefinitionService.seedNodes()
- .forEach(node -> store.addNode(node.id(), node.ip(), node.tcpPort()));
+ clusterMetadataService.getClusterMetadata()
+ .getNodes()
+ .forEach(node -> store.addNode(node.id(), node.ip(), node.tcpPort()));
log.info("Started");
}
@@ -119,11 +127,16 @@ public class ClusterManager
}
@Override
- public void formCluster(Set<ControllerNode> nodes, String ipPrefix) {
+ public void formCluster(Set<ControllerNode> nodes) {
checkNotNull(nodes, "Nodes cannot be null");
checkArgument(!nodes.isEmpty(), "Nodes cannot be empty");
- checkNotNull(ipPrefix, "IP prefix cannot be null");
- clusterDefinitionService.formCluster(nodes, ipPrefix);
+
+ ClusterMetadata metadata = ClusterMetadata.builder()
+ .withName("default")
+ .withControllerNodes(nodes)
+ .withPartitions(buildDefaultPartitions(nodes))
+ .build();
+ clusterMetadataService.setClusterMetadata(metadata);
try {
log.warn("Shutting down container for cluster reconfiguration!");
systemService.reboot("now", SystemService.Swipe.NONE);
@@ -153,4 +166,21 @@ public class ClusterManager
post(event);
}
}
+
+ private static Collection<Partition> buildDefaultPartitions(Collection<ControllerNode> nodes) {
+ List<ControllerNode> sorted = new ArrayList<>(nodes);
+ Collections.sort(sorted, (o1, o2) -> o1.id().toString().compareTo(o2.id().toString()));
+ Collection<Partition> partitions = Lists.newArrayList();
+
+ int length = nodes.size();
+ int count = 3;
+ for (int i = 0; i < length; i++) {
+ Set<NodeId> set = new HashSet<>(count);
+ for (int j = 0; j < count; j++) {
+ set.add(sorted.get((i + j) % length).id());
+ }
+ partitions.add(new Partition("p" + (i + 1), set));
+ }
+ return partitions;
+ }
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
new file mode 100644
index 00000000..a0f7a833
--- /dev/null
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
@@ -0,0 +1,116 @@
+package org.onosproject.cluster.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collection;
+import java.util.Enumeration;
+
+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.packet.IpAddress;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataEventListener;
+import org.onosproject.cluster.ClusterMetadataService;
+import org.onosproject.cluster.ClusterMetadataStore;
+import org.onosproject.cluster.ClusterMetadataStoreDelegate;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.store.service.Versioned;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of ClusterMetadataService.
+ */
+@Component(immediate = true)
+@Service
+public class ClusterMetadataManager
+ extends AbstractListenerManager<ClusterMetadataEvent, ClusterMetadataEventListener>
+ implements ClusterMetadataService {
+
+ private ControllerNode localNode;
+ private final Logger log = getLogger(getClass());
+
+ private ClusterMetadataStoreDelegate delegate = new InternalStoreDelegate();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterMetadataStore store;
+
+ @Activate
+ public void activate() {
+ store.setDelegate(delegate);
+ eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
+ establishSelfIdentity();
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(ClusterMetadataEvent.class);
+ log.info("Stopped");
+ }
+
+ @Override
+ public ClusterMetadata getClusterMetadata() {
+ return Versioned.valueOrElse(store.getClusterMetadata(), null);
+ }
+
+ @Override
+ public ControllerNode getLocalNode() {
+ return localNode;
+ }
+
+ @Override
+ public void setClusterMetadata(ClusterMetadata metadata) {
+ checkNotNull(metadata, "Cluster metadata cannot be null");
+ store.setClusterMetadata(metadata);
+ }
+
+ // Store delegate to re-post events emitted from the store.
+ private class InternalStoreDelegate implements ClusterMetadataStoreDelegate {
+ @Override
+ public void notify(ClusterMetadataEvent event) {
+ post(event);
+ }
+ }
+
+ private IpAddress findLocalIp(Collection<ControllerNode> controllerNodes) throws SocketException {
+ Enumeration<NetworkInterface> interfaces =
+ NetworkInterface.getNetworkInterfaces();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface iface = interfaces.nextElement();
+ Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
+ while (inetAddresses.hasMoreElements()) {
+ IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
+ if (controllerNodes.stream()
+ .map(ControllerNode::ip)
+ .anyMatch(nodeIp -> ip.equals(nodeIp))) {
+ return ip;
+ }
+ }
+ }
+ throw new IllegalStateException("Unable to determine local ip");
+ }
+
+ private void establishSelfIdentity() {
+ try {
+ IpAddress ip = findLocalIp(getClusterMetadata().getNodes());
+ localNode = getClusterMetadata().getNodes()
+ .stream()
+ .filter(node -> node.ip().equals(ip))
+ .findFirst()
+ .get();
+ } catch (SocketException e) {
+ throw new IllegalStateException("Cannot determine local IP", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
index 19377cf6..8f601497 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
@@ -112,10 +112,10 @@ public final class OpticalPortOperator implements ConfigOperator {
return new OduCltPortDescription(port, odu.isEnabled(), odu.signalType(), sa);
case PACKET:
case FIBER:
+ case COPPER:
return new DefaultPortDescription(port, descr.isEnabled(), descr.type(),
descr.portSpeed(), sa);
default:
- // this includes copper ports.
log.warn("Unsupported optical port type {} - can't update", descr.type());
return descr;
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
index 137aca1e..0a1af6f5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
@@ -29,9 +29,11 @@ import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
@@ -155,6 +157,7 @@ public final class FlowObjectiveCompositionUtil {
return treatmentBuilder.build();
}
+ //CHECKSTYLE:OFF
public static TrafficSelector revertTreatmentSelector(TrafficTreatment trafficTreatment,
TrafficSelector trafficSelector) {
@@ -195,14 +198,30 @@ public final class FlowObjectiveCompositionUtil {
} else {
return null;
}
- } else {
- break;
}
default:
break;
}
break;
}
+ case L1MODIFICATION: {
+ L1ModificationInstruction l1 = (L1ModificationInstruction) instruction;
+ switch (l1.subtype()) {
+ case ODU_SIGID:
+ if (criterionMap.containsKey(Criterion.Type.ODU_SIGID)) {
+ if (((OduSignalIdCriterion) criterionMap.get((Criterion.Type.ODU_SIGID))).oduSignalId()
+ .equals(((L1ModificationInstruction.ModOduSignalIdInstruction) l1)
+ .oduSignalId())) {
+ criterionMap.remove(Criterion.Type.ODU_SIGID);
+ } else {
+ return null;
+ }
+ }
+ default:
+ break;
+ }
+ break;
+ }
case L2MODIFICATION: {
L2ModificationInstruction l2 = (L2ModificationInstruction) instruction;
switch (l2.subtype()) {
@@ -344,6 +363,7 @@ public final class FlowObjectiveCompositionUtil {
return selectorBuilder.build();
}
+ //CHECKSTYLE:ON
public static Set<Criterion.Type> getTypeSet(TrafficSelector trafficSelector) {
Set<Criterion.Type> typeSet = new HashSet<>();
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
index 5fd1c85d..acc5a5d5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
@@ -24,12 +24,14 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -46,24 +48,23 @@ import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.net.link.LinkStore;
-import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
+import org.onosproject.net.newresource.ResourcePath;
+import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceRequest;
-import org.onosproject.net.resource.link.LinkResourceService;
-import org.onosproject.net.resource.link.MplsLabel;
-import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
-import org.onosproject.net.resource.ResourceAllocation;
-import org.onosproject.net.resource.ResourceType;
import org.slf4j.Logger;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.LinkKey.linkKey;
import static org.slf4j.LoggerFactory.getLogger;
@Component(immediate = true)
@@ -78,18 +79,15 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService resourceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkStore linkStore;
+ protected ResourceService resourceService;
protected ApplicationId appId;
@Override
public List<Intent> compile(MplsPathIntent intent, List<Intent> installable,
Set<LinkResourceAllocations> resources) {
- LinkResourceAllocations allocations = assignMplsLabel(intent);
- List<FlowRule> rules = generateRules(intent, allocations);
+ Map<LinkKey, MplsLabel> labels = assignMplsLabel(intent);
+ List<FlowRule> rules = generateRules(intent, labels);
return Collections.singletonList(new FlowRuleIntent(appId, rules, intent.resources()));
}
@@ -105,39 +103,60 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
intentExtensionService.unregisterCompiler(MplsPathIntent.class);
}
- private LinkResourceAllocations assignMplsLabel(MplsPathIntent intent) {
+ private Map<LinkKey, MplsLabel> assignMplsLabel(MplsPathIntent intent) {
// TODO: do it better... Suggestions?
- Set<Link> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
+ Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
.links().size() - 2);
for (int i = 1; i <= intent.path().links().size() - 2; i++) {
- Link link = intent.path().links().get(i);
+ LinkKey link = linkKey(intent.path().links().get(i));
linkRequest.add(link);
// add the inverse link. I want that the label is reserved both for
// the direct and inverse link
- linkRequest.add(linkStore.getLink(link.dst(), link.src()));
+ linkRequest.add(linkKey(link.dst(), link.src()));
}
- LinkResourceRequest.Builder request = DefaultLinkResourceRequest
- .builder(intent.id(), linkRequest).addMplsRequest();
- LinkResourceAllocations reqMpls = resourceService
- .requestResources(request.build());
- return reqMpls;
- }
+ Map<LinkKey, MplsLabel> labels = findMplsLabels(linkRequest);
+ if (labels.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ List<ResourcePath> resources = labels.entrySet().stream()
+ .map(x -> new ResourcePath(linkKey(x.getKey().src(), x.getKey().src()), x.getValue()))
+ .collect(Collectors.toList());
+ List<org.onosproject.net.newresource.ResourceAllocation> allocations =
+ resourceService.allocate(intent.id(), resources);
+ if (allocations.isEmpty()) {
+ Collections.emptyMap();
+ }
- private MplsLabel getMplsLabel(LinkResourceAllocations allocations, Link link) {
- for (ResourceAllocation allocation : allocations
- .getResourceAllocation(link)) {
- if (allocation.type() == ResourceType.MPLS_LABEL) {
- return ((MplsLabelResourceAllocation) allocation).mplsLabel();
+ return labels;
+ }
+ private Map<LinkKey, MplsLabel> findMplsLabels(Set<LinkKey> links) {
+ Map<LinkKey, MplsLabel> labels = new HashMap<>();
+ for (LinkKey link : links) {
+ Optional<MplsLabel> label = findMplsLabel(link);
+ if (label.isPresent()) {
+ labels.put(link, label.get());
}
}
- log.warn("MPLS label was not assigned successfully");
- return null;
+
+ return labels;
+ }
+
+ private Optional<MplsLabel> findMplsLabel(LinkKey link) {
+ return resourceService.getAvailableResources(new ResourcePath(link)).stream()
+ .filter(x -> x.lastComponent() instanceof MplsLabel)
+ .map(x -> (MplsLabel) x.lastComponent())
+ .findFirst();
+ }
+
+ private MplsLabel getMplsLabel(Map<LinkKey, MplsLabel> labels, LinkKey link) {
+ return labels.get(link);
}
private List<FlowRule> generateRules(MplsPathIntent intent,
- LinkResourceAllocations allocations) {
+ Map<LinkKey, MplsLabel> labels) {
Iterator<Link> links = intent.path().links().iterator();
Link srcLink = links.next();
@@ -149,7 +168,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
// Ingress traffic
// Get the new MPLS label
- MplsLabel mpls = getMplsLabel(allocations, link);
+ MplsLabel mpls = getMplsLabel(labels, linkKey(link));
checkNotNull(mpls);
MplsLabel prevLabel = mpls;
rules.add(ingressFlow(prev.port(), link, intent, mpls));
@@ -163,7 +182,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
if (links.hasNext()) {
// Transit traffic
// Get the new MPLS label
- mpls = getMplsLabel(allocations, link);
+ mpls = getMplsLabel(labels, linkKey(link));
checkNotNull(mpls);
rules.add(transitFlow(prev.port(), link, intent,
prevLabel, mpls));
@@ -181,7 +200,8 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule ingressFlow(PortNumber inPort, Link link,
- MplsPathIntent intent, MplsLabel label) {
+ MplsPathIntent intent,
+ MplsLabel label) {
TrafficSelector.Builder ingressSelector = DefaultTrafficSelector
.builder(intent.selector());
@@ -193,10 +213,10 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
.matchMplsLabel(intent.ingressLabel().get());
// Swap the MPLS label
- treat.setMpls(label.label());
+ treat.setMpls(label);
} else {
// Push and set the MPLS label
- treat.pushMpls().setMpls(label.label());
+ treat.pushMpls().setMpls(label);
}
// Add the output action
treat.setOutput(link.src().port());
@@ -205,21 +225,21 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule transitFlow(PortNumber inPort, Link link,
- MplsPathIntent intent,
- MplsLabel prevLabel,
- MplsLabel outLabel) {
+ MplsPathIntent intent,
+ MplsLabel prevLabel,
+ MplsLabel outLabel) {
// Ignore the ingress Traffic Selector and use only the MPLS label
// assigned in the previous link
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchInPort(inPort).matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(prevLabel.label());
+ .matchMplsLabel(prevLabel);
TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
// Set the new label only if the label on the packet is
// different
if (!prevLabel.equals(outLabel)) {
- treat.setMpls(outLabel.label());
+ treat.setMpls(outLabel);
}
treat.setOutput(link.src().port());
@@ -227,14 +247,14 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule egressFlow(PortNumber inPort, Link link,
- MplsPathIntent intent,
- MplsLabel prevLabel) {
+ MplsPathIntent intent,
+ MplsLabel prevLabel) {
// egress point: either set the egress MPLS label or pop the
// MPLS label based on the intent annotations
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchInPort(inPort).matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(prevLabel.label());
+ .matchMplsLabel(prevLabel);
// apply the intent's treatments
TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder(intent
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
index c6eb7c5a..fce8498c 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
@@ -17,6 +17,7 @@ package org.onosproject.net.intent.impl.compiler;
import org.apache.commons.lang3.tuple.Pair;
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.Modified;
import org.apache.felix.scr.annotations.Property;
@@ -70,7 +71,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* An intent compiler for {@link org.onosproject.net.intent.OpticalCircuitIntent}.
*/
// For now, remove component designation until dependency on the new resource manager is available.
-// @Component(immediate = true)
+@Component(immediate = true)
public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircuitIntent> {
private static final Logger log = LoggerFactory.getLogger(OpticalCircuitIntentCompiler.class);
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
index eb5b4af8..d6725b7c 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
@@ -16,7 +16,11 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
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;
@@ -24,6 +28,7 @@ import org.onlab.util.Frequency;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Link;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
@@ -38,32 +43,29 @@ import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalPathIntent;
import org.onosproject.net.intent.impl.IntentCompilationException;
+import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourcePath;
import org.onosproject.net.newresource.ResourceService;
-import org.onosproject.net.resource.ResourceType;
-import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
-import org.onosproject.net.resource.link.LambdaResource;
-import org.onosproject.net.resource.link.LambdaResourceAllocation;
import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceRequest;
-import org.onosproject.net.resource.link.LinkResourceService;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.net.LinkKey.linkKey;
/**
* An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
*/
// For now, remove component designation until dependency on the new resource manager is available.
-// @Component(immediate = true)
+@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
@@ -80,9 +82,6 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceService resourceService;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService linkResourceService;
-
@Activate
public void activate() {
intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
@@ -138,13 +137,12 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
ochSignal = srcOchPort.lambda();
} else {
// Request and reserve lambda on path
- LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
- if (linkAllocs == null) {
+ IndexedLambda lambda = assignWavelength(intent, path);
+ if (lambda == null) {
continue;
}
- LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
- ochSignal = new OchSignal(lambdaAlloc.lambda().toInt(), omsPort.maxFrequency(), omsPort.grid());
+ ochSignal = new OchSignal((int) lambda.index(), omsPort.maxFrequency(), omsPort.grid());
}
// Create installable optical path intent
@@ -171,72 +169,46 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
}
/**
- * Find the lambda allocated to the path.
- *
- * @param path the path
- * @param linkAllocs the link allocations
- * @return lambda allocated to the given path
- */
- private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
- return path.links().stream()
- .flatMap(x -> linkAllocs.getResourceAllocation(x).stream())
- .filter(x -> x.type() == ResourceType.LAMBDA)
- .findFirst()
- .map(x -> (LambdaResourceAllocation) x)
- .orElse(null);
- }
-
- /**
* Request and reserve first available wavelength across path.
*
* @param path path in WDM topology
- * @return first available lambda resource allocation
+ * @return first available lambda allocated
*/
- private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
- LinkResourceRequest.Builder request =
- DefaultLinkResourceRequest.builder(intent.id(), path.links())
- .addLambdaRequest();
-
- LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
-
- if (!checkWavelengthContinuity(allocations, path)) {
- linkResourceService.releaseResources(allocations);
+ private IndexedLambda assignWavelength(Intent intent, Path path) {
+ Set<IndexedLambda> lambdas = findCommonLambdasOverLinks(path.links());
+ if (lambdas.isEmpty()) {
return null;
}
- return allocations;
- }
+ IndexedLambda minLambda = findFirstLambda(lambdas);
+ List<ResourcePath> lambdaResources = path.links().stream()
+ .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(x -> ResourcePath.child(x, minLambda))
+ .collect(Collectors.toList());
- /**
- * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
- * @return true if wavelength continuity is met, false otherwise
- */
- private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
- if (allocations == null) {
- return false;
+ List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources);
+ if (allocations.isEmpty()) {
+ log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources);
}
- List<LambdaResource> lambdas = path.links().stream()
- .flatMap(x -> allocations.getResourceAllocation(x).stream())
- .filter(x -> x.type() == ResourceType.LAMBDA)
- .map(x -> ((LambdaResourceAllocation) x).lambda())
- .collect(Collectors.toList());
+ return minLambda;
+ }
- LambdaResource lambda = null;
- for (LambdaResource nextLambda: lambdas) {
- if (nextLambda == null) {
- return false;
- }
- if (lambda == null) {
- lambda = nextLambda;
- continue;
- }
- if (!lambda.equals(nextLambda)) {
- return false;
- }
- }
+ private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) {
+ return links.stream()
+ .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(resourceService::getAvailableResources)
+ .map(x -> Iterables.filter(x, r -> r.lastComponent() instanceof IndexedLambda))
+ .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.lastComponent()))
+ .map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x))
+ .reduce(Sets::intersection)
+ .orElse(Collections.emptySet());
+ }
- return true;
+ private IndexedLambda findFirstLambda(Set<IndexedLambda> lambdas) {
+ return lambdas.stream()
+ .findFirst()
+ .get();
}
private ConnectPoint staticPort(ConnectPoint connectPoint) {
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
index 5226967f..10fe75ea 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
@@ -41,7 +41,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* An implementation of ResourceService.
*/
-@Component(immediate = true, enabled = false)
+@Component(immediate = true)
@Service
@Beta
public final class ResourceManager implements ResourceService, ResourceAdminService {
@@ -127,6 +127,17 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ
}
@Override
+ public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
+ checkNotNull(parent);
+
+ Collection<ResourcePath> children = store.getChildResources(parent);
+ return children.stream()
+ // We access store twice in this method, then the store may be updated by others
+ .filter(x -> !store.getConsumer(x).isPresent())
+ .collect(Collectors.toList());
+ }
+
+ @Override
public boolean isAvailable(ResourcePath resource) {
checkNotNull(resource);
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
index 8b9952ed..7eb189e5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
@@ -31,7 +31,6 @@ import org.onosproject.net.resource.ResourceType;
import org.onosproject.net.resource.link.BandwidthResourceAllocation;
import org.onosproject.net.resource.link.BandwidthResourceRequest;
import org.onosproject.net.resource.link.DefaultLinkResourceAllocations;
-import org.onosproject.net.resource.link.LambdaResource;
import org.onosproject.net.resource.link.LambdaResourceAllocation;
import org.onosproject.net.resource.link.LambdaResourceRequest;
import org.onosproject.net.resource.link.LinkResourceAllocations;
@@ -46,15 +45,12 @@ import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
import org.onosproject.net.resource.link.MplsLabelResourceRequest;
import org.slf4j.Logger;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
@@ -86,67 +82,6 @@ public class LinkResourceManager
log.info("Stopped");
}
- /**
- * Returns available lambdas on specified link.
- *
- * @param link the link
- * @return available lambdas on specified link
- */
- private Set<LambdaResource> getAvailableLambdas(Link link) {
- checkNotNull(link);
- Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
- if (resAllocs == null) {
- return Collections.emptySet();
- }
- Set<LambdaResource> lambdas = new HashSet<>();
- for (ResourceAllocation res : resAllocs) {
- if (res.type() == ResourceType.LAMBDA) {
- lambdas.add(((LambdaResourceAllocation) res).lambda());
- }
- }
- return lambdas;
- }
-
-
- /**
- * Returns available lambdas on specified links.
- *
- * @param links the links
- * @return available lambdas on specified links
- */
- private Iterable<LambdaResource> getAvailableLambdas(Iterable<Link> links) {
- checkNotNull(links);
- Iterator<Link> i = links.iterator();
- checkArgument(i.hasNext());
- Set<LambdaResource> lambdas = new HashSet<>(getAvailableLambdas(i.next()));
- while (i.hasNext()) {
- lambdas.retainAll(getAvailableLambdas(i.next()));
- }
- return lambdas;
- }
-
-
- /**
- * Returns available MPLS label on specified link.
- *
- * @param link the link
- * @return available MPLS labels on specified link
- */
- private Iterable<MplsLabel> getAvailableMplsLabels(Link link) {
- Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
- if (resAllocs == null) {
- return Collections.emptySet();
- }
- Set<MplsLabel> mplsLabels = new HashSet<>();
- for (ResourceAllocation res : resAllocs) {
- if (res.type() == ResourceType.MPLS_LABEL) {
-
- mplsLabels.add(((MplsLabelResourceAllocation) res).mplsLabel());
- }
- }
-
- return mplsLabels;
- }
@Override
public LinkResourceAllocations requestResources(LinkResourceRequest req) {
@@ -164,26 +99,23 @@ public class LinkResourceManager
allocs.add(new BandwidthResourceAllocation(br.bandwidth()));
break;
case LAMBDA:
- Iterator<LambdaResource> lambdaIterator =
- getAvailableLambdas(req.links()).iterator();
- if (lambdaIterator.hasNext()) {
- allocs.add(new LambdaResourceAllocation(lambdaIterator.next()));
- } else {
- log.info("Failed to allocate lambda resource.");
- return null;
- }
+ LambdaResourceRequest lr = (LambdaResourceRequest) r;
+ allocs.add(new LambdaResourceAllocation(lr.lambda()));
break;
case MPLS_LABEL:
for (Link link : req.links()) {
if (allocsPerLink.get(link) == null) {
allocsPerLink.put(link, new HashSet<>());
}
- Iterator<MplsLabel> mplsIter = getAvailableMplsLabels(link)
- .iterator();
- if (mplsIter.hasNext()) {
- allocsPerLink.get(link)
- .add(new MplsLabelResourceAllocation(mplsIter
- .next()));
+
+ Optional<MplsLabel> label = req.resources(link).stream()
+ .filter(x -> x.type() == ResourceType.MPLS_LABEL)
+ .map(x -> (MplsLabelResourceRequest) x)
+ .map(MplsLabelResourceRequest::mplsLabel)
+ .findFirst();
+
+ if (label.isPresent()) {
+ allocsPerLink.get(link).add(new MplsLabelResourceAllocation(label.get()));
} else {
log.info("Failed to allocate MPLS resource.");
break;
@@ -258,10 +190,12 @@ public class LinkResourceManager
((BandwidthResourceAllocation) alloc).bandwidth()));
break;
case LAMBDA:
- result.add(new LambdaResourceRequest());
+ result.add(new LambdaResourceRequest(
+ ((LambdaResourceAllocation) alloc).lambda()));
break;
case MPLS_LABEL:
- result.add(new MplsLabelResourceRequest());
+ result.add(new MplsLabelResourceRequest(
+ ((MplsLabelResourceAllocation) alloc).mplsLabel()));
break;
default:
break;
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
new file mode 100644
index 00000000..06b2c81e
--- /dev/null
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
@@ -0,0 +1,100 @@
+/*
+ * 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.intent.impl.compiler;
+
+import com.google.common.collect.ImmutableList;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.net.newresource.ResourceAllocation;
+import org.onosproject.net.newresource.ResourceConsumer;
+import org.onosproject.net.newresource.ResourcePath;
+import org.onosproject.net.newresource.ResourceService;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+class MockResourceService implements ResourceService {
+
+ private final Map<ResourcePath, ResourceConsumer> assignment = new HashMap<>();
+
+ @Override
+ public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<ResourcePath> resources) {
+ assignment.putAll(
+ resources.stream().collect(Collectors.toMap(x -> x, x -> consumer))
+ );
+
+ return resources.stream()
+ .map(x -> new ResourceAllocation(x, consumer))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean release(List<ResourceAllocation> allocations) {
+ allocations.forEach(x -> assignment.remove(x.resource()));
+
+ return true;
+ }
+
+ @Override
+ public boolean release(ResourceConsumer consumer) {
+ List<ResourcePath> resources = assignment.entrySet().stream()
+ .filter(x -> x.getValue().equals(consumer))
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ List<ResourceAllocation> allocations = resources.stream()
+ .map(x -> new ResourceAllocation(x, consumer))
+ .collect(Collectors.toList());
+
+ return release(allocations);
+ }
+
+ @Override
+ public Optional<ResourceAllocation> getResourceAllocation(ResourcePath resource) {
+ return Optional.ofNullable(assignment.get(resource))
+ .map(x -> new ResourceAllocation(resource, x));
+ }
+
+ @Override
+ public <T> Collection<ResourceAllocation> getResourceAllocations(ResourcePath parent, Class<T> cls) {
+ return assignment.entrySet().stream()
+ .filter(x -> x.getKey().parent().isPresent())
+ .filter(x -> x.getKey().parent().get().equals(parent))
+ .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
+ return assignment.entrySet().stream()
+ .filter(x -> x.getValue().equals(consumer))
+ .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
+ ResourcePath resource = ResourcePath.child(parent, MplsLabel.mplsLabel(10));
+ return ImmutableList.of(resource);
+ }
+
+ @Override
+ public boolean isAvailable(ResourcePath resource) {
+ return true;
+ }
+}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
index 771a9883..6cceee12 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
@@ -41,10 +41,8 @@ import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentTestsMocks;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.store.trivial.SimpleLinkStore;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@@ -52,6 +50,7 @@ import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.PID;
@@ -61,10 +60,12 @@ public class MplsPathIntentCompilerTest {
private final ApplicationId appId = new TestApplicationId("test");
+ private final ConnectPoint d1pi = connectPoint("s1", 100);
private final ConnectPoint d1p1 = connectPoint("s1", 0);
private final ConnectPoint d2p0 = connectPoint("s2", 0);
private final ConnectPoint d2p1 = connectPoint("s2", 1);
private final ConnectPoint d3p1 = connectPoint("s3", 1);
+ private final ConnectPoint d3pe = connectPoint("s3", 100);
private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
@@ -75,8 +76,10 @@ public class MplsPathIntentCompilerTest {
Optional.of(MplsLabel.mplsLabel(20));
private final List<Link> links = Arrays.asList(
+ createEdgeLink(d1pi, true),
new DefaultLink(PID, d1p1, d2p0, DIRECT),
- new DefaultLink(PID, d2p1, d3p1, DIRECT)
+ new DefaultLink(PID, d2p1, d3p1, DIRECT),
+ createEdgeLink(d3pe, false)
);
private IdGenerator idGenerator = new MockIdGenerator();
@@ -92,8 +95,7 @@ public class MplsPathIntentCompilerTest {
expect(coreService.registerApplication("org.onosproject.net.intent"))
.andReturn(appId);
sut.coreService = coreService;
- sut.linkStore = new SimpleLinkStore();
- sut.resourceService = new IntentTestsMocks.MockResourceService();
+ sut.resourceService = new MockResourceService();
Intent.bindIdGenerator(idGenerator);
@@ -128,7 +130,7 @@ public class MplsPathIntentCompilerTest {
assertThat(compiled, hasSize(1));
Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
- assertThat(rules, hasSize(1));
+ assertThat(rules, hasSize(3));
FlowRule rule = rules.stream()
.filter(x -> x.deviceId().equals(d2p0.deviceId()))
@@ -139,4 +141,5 @@ public class MplsPathIntentCompilerTest {
sut.deactivate();
}
+
}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
index 1a160d98..3e806a73 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
@@ -21,11 +21,19 @@ import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPacket;
+import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onlab.packet.ndp.NeighborAdvertisement;
+import org.onlab.packet.ndp.NeighborDiscoveryOptions;
+import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
@@ -66,9 +74,13 @@ import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
@@ -83,6 +95,8 @@ public class ProxyArpManagerTest {
private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
+ private static final Ip6Address IP3 = Ip6Address.valueOf("1000::1");
+ private static final Ip6Address IP4 = Ip6Address.valueOf("1000::2");
private static final ProviderId PID = new ProviderId("of", "foo");
@@ -90,8 +104,14 @@ public class ProxyArpManagerTest {
private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01");
private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
+ private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
+ private static final MacAddress MAC4 = MacAddress.valueOf("00:00:44:00:00:04");
+ private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01");
private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
+ private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
+ private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);
+ private static final HostId SOLICITED_HID3 = HostId.hostId(SOLICITED_MAC3, VLAN1);
private static final DeviceId DID1 = getDeviceId(1);
private static final DeviceId DID2 = getDeviceId(2);
@@ -222,21 +242,29 @@ public class ProxyArpManagerTest {
for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) {
ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
- Ip4Prefix prefix1 =
- Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
- Ip4Address addr1 =
- Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
+
+ // Interface address for IPv4
+ Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
+ Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24");
Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
- Interface intf1 = new Interface(cp, Sets.newHashSet(ia1),
+
+ // Interface address for IPv6
+ Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64");
+ Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1");
+ Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64");
+ Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::1");
+ InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3);
+ InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4);
+
+ Interface intf1 = new Interface(cp, Sets.newHashSet(ia1, ia3),
MacAddress.valueOf(2 * i - 1),
VlanId.vlanId((short) 1));
- Interface intf2 = new Interface(cp, Sets.newHashSet(ia2),
+ Interface intf2 = new Interface(cp, Sets.newHashSet(ia2, ia4),
MacAddress.valueOf(2 * i),
VlanId.NONE);
-
interfaces.add(intf1);
interfaces.add(intf2);
@@ -321,6 +349,41 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known.
+ * Verifies the correct NDP reply is sent out the correct port.
+ */
+ @Test
+ public void testReplyKnownIpv6() {
+ //Set the return value of isEdgePoint from the edgemanager.
+ isEdgePointReturn = true;
+
+ Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4),
+ Collections.singleton(IP3));
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.singleton(replyer));
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ proxyArp.reply(ndpRequest, getLocation(5));
+
+ assertEquals(1, packetService.packets.size());
+ Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ MAC3, MAC4, IP3, IP4);
+ verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0));
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
* destination host is not known.
* Verifies the ARP request is flooded out the correct edge ports.
*/
@@ -337,7 +400,6 @@ public class ProxyArpManagerTest {
.andReturn(Collections.emptySet());
expect(hostService.getHost(HID2)).andReturn(requestor);
-
replay(hostService);
replay(interfaceService);
@@ -355,6 +417,41 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is not known.
+ * Verifies the NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testReplyUnknownIpv6() {
+ isEdgePointReturn = true;
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.emptySet());
+ expect(interfaceService.getInterfacesByIp(IP4))
+ .andReturn(Collections.emptySet());
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //Setup the set of edge ports to be used in the reply method
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+
+ proxyArp.reply(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
* destination host is known for that IP address, but is not on the same
* VLAN as the source host.
* Verifies the ARP request is flooded out the correct edge ports.
@@ -388,6 +485,46 @@ public class ProxyArpManagerTest {
verifyFlood(arpRequest);
}
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known for that IP address, but is not on the same
+ * VLAN as the source host.
+ * Verifies the NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testReplyDifferentVlanIpv6() {
+
+ Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(4),
+ Collections.singleton(IP3));
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.singleton(replyer));
+ expect(interfaceService.getInterfacesByIp(IP4))
+ .andReturn(Collections.emptySet());
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //Setup for flood test
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+ proxyArp.reply(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
+ * Test ARP request from external network to an internal host.
+ */
@Test
public void testReplyToRequestForUs() {
Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
@@ -422,6 +559,63 @@ public class ProxyArpManagerTest {
verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
}
+ /**
+ * Test NDP request from external network to an internal host.
+ */
+ @Test
+ public void testReplyToRequestForUsIpv6() {
+ Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
+ Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1");
+ Ip6Address ourSecondIp = Ip6Address.valueOf("2000::1");
+ MacAddress firstMac = MacAddress.valueOf(1L);
+ MacAddress secondMac = MacAddress.valueOf(2L);
+
+ Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
+ Collections.singleton(theirIp));
+
+ expect(hostService.getHost(HID2)).andReturn(requestor);
+ expect(hostService.getHostsByIp(ourFirstIp))
+ .andReturn(Collections.singleton(requestor));
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC2,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ ourFirstIp);
+ isEdgePointReturn = true;
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(1, packetService.packets.size());
+
+ Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ firstMac,
+ MAC2,
+ ourFirstIp,
+ theirIp);
+ verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
+
+ // Test a request for the second address on that port
+ packetService.packets.clear();
+ ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC2,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ ourSecondIp);
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(1, packetService.packets.size());
+
+ ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ secondMac,
+ MAC2,
+ ourSecondIp,
+ theirIp);
+ verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
+ }
+
+ /**
+ * Request for a valid external IPv4 address but coming in the wrong port.
+ */
@Test
public void testReplyExternalPortBadRequest() {
replay(hostService); // no further host service expectations
@@ -442,6 +636,38 @@ public class ProxyArpManagerTest {
assertEquals(0, packetService.packets.size());
}
+ /**
+ * Request for a valid external IPv6 address but coming in the wrong port.
+ */
+ @Test
+ public void testReplyExternalPortBadRequestIpv6() {
+ replay(hostService); // no further host service expectations
+ replay(interfaceService);
+
+ Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC1,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ Ip6Address.valueOf("3000::1"));
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(0, packetService.packets.size());
+
+ // Request for a valid internal IP address but coming in an external port
+ packetService.packets.clear();
+ ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC1,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ IP3);
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(0, packetService.packets.size());
+ }
+
+ /**
+ * Test ARP request from internal network to an external host.
+ */
@Test
public void testReplyToRequestFromUs() {
Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
@@ -474,6 +700,48 @@ public class ProxyArpManagerTest {
}
/**
+ * Test NDP request from internal network to an external host.
+ */
+ @Test
+ public void testReplyToRequestFromUsIpv6() {
+ Ip6Address ourIp = Ip6Address.valueOf("1000::1");
+ MacAddress ourMac = MacAddress.valueOf(1L);
+ Ip6Address theirIp = Ip6Address.valueOf("1000::100");
+
+ expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
+ expect(interfaceService.getInterfacesByIp(ourIp))
+ .andReturn(Collections.singleton(new Interface(getLocation(1),
+ Collections.singleton(new InterfaceIpAddress(
+ ourIp,
+ IpPrefix.valueOf("1000::1/64"))),
+ ourMac,
+ VLAN1)));
+ expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
+ replay(hostService);
+ replay(interfaceService);
+
+ // This is a request from something inside our network (like a BGP
+ // daemon) to an external host.
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ ourMac,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ ourIp,
+ theirIp);
+
+ //Ensure the packet is allowed through (it is not to an internal port)
+ isEdgePointReturn = true;
+
+ proxyArp.reply(ndpRequest, getLocation(5));
+ assertEquals(1, packetService.packets.size());
+ verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0));
+
+ // The same request from a random external port should fail
+ packetService.packets.clear();
+ proxyArp.reply(ndpRequest, getLocation(2));
+ assertEquals(0, packetService.packets.size());
+ }
+
+ /**
* Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
* destination host is known.
* Verifies the correct ARP request is sent out the correct port.
@@ -502,6 +770,35 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known.
+ * Verifies the correct ARP request is sent out the correct port.
+ */
+ @Test
+ public void testForwardToHostIpv6() {
+ Host host1 = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1,
+ Collections.singleton(IP3));
+ Host host2 = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2,
+ Collections.singleton(IP4));
+
+ expect(hostService.getHost(SOLICITED_HID3)).andReturn(host1);
+ expect(hostService.getHost(HID4)).andReturn(host2);
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ proxyArp.forward(ndpRequest, LOC2);
+
+ assertEquals(1, packetService.packets.size());
+ OutboundPacket packet = packetService.packets.get(0);
+
+ verifyPacketOut(ndpRequest, LOC1, packet);
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
* destination host is not known.
* Verifies the correct ARP request is flooded out the correct edge ports.
*/
@@ -526,6 +823,33 @@ public class ProxyArpManagerTest {
}
/**
+ * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
+ * destination host is not known.
+ * Verifies the correct NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testForwardFloodIpv6() {
+ expect(hostService.getHost(SOLICITED_HID3)).andReturn(null);
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //populate the list of edges when so that when forward hits flood in the manager it contains the values
+ //that should continue on
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("3"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+
+ proxyArp.forward(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
* Verifies that the given packet was flooded out all available edge ports,
* except for the input port.
*
@@ -626,6 +950,61 @@ public class ProxyArpManagerTest {
}
/**
+ * Builds an NDP packet with the given parameters.
+ *
+ * @param type NeighborSolicitation or NeighborAdvertisement
+ * @param srcMac source MAC address
+ * @param dstMac destination MAC address, or null if this is a request
+ * @param srcIp source IP address
+ * @param dstIp destination IP address
+ * @return the NDP packet
+ */
+ private Ethernet buildNDP(byte type, MacAddress srcMac, MacAddress dstMac,
+ Ip6Address srcIp, Ip6Address dstIp) {
+ assertThat(type, anyOf(
+ is(ICMP6.NEIGHBOR_SOLICITATION),
+ is(ICMP6.NEIGHBOR_ADVERTISEMENT)
+ ));
+ assertNotNull(srcMac);
+ assertNotNull(dstMac);
+ assertNotNull(srcIp);
+ assertNotNull(dstIp);
+
+ IPacket ndp;
+ if (type == ICMP6.NEIGHBOR_SOLICITATION) {
+ ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets());
+ } else {
+ ndp = new NeighborAdvertisement()
+ .setSolicitedFlag((byte) 1)
+ .setOverrideFlag((byte) 1)
+ .setTargetAddress(srcIp.toOctets())
+ .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
+ srcMac.toBytes());
+ }
+
+ ICMP6 icmp6 = new ICMP6();
+ icmp6.setIcmpType(type);
+ icmp6.setIcmpCode((byte) 0);
+ icmp6.setPayload(ndp);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setDestinationAddress(dstIp.toOctets());
+ ipv6.setSourceAddress(srcIp.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
+ ipv6.setHopLimit((byte) 255);
+ ipv6.setPayload(icmp6);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(dstMac);
+ eth.setSourceMACAddress(srcMac);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setVlanID(VLAN1.toShort());
+ eth.setPayload(ipv6);
+
+ return eth;
+ }
+
+ /**
* Test PacketService implementation that simply stores OutboundPackets
* passed to {@link #emit(OutboundPacket)} for later verification.
*/
diff --git a/framework/src/onos/core/store/dist/pom.xml b/framework/src/onos/core/store/dist/pom.xml
index cc293da4..f2ec2a71 100644
--- a/framework/src/onos/core/store/dist/pom.xml
+++ b/framework/src/onos/core/store/dist/pom.xml
@@ -71,7 +71,7 @@
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
- <version>1.0.7</version>
+ <version>1.0.8</version>
</dependency>
<dependency>
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java
deleted file mode 100644
index 75f05a31..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.cluster.impl;
-
-import java.util.Set;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Cluster definition.
- */
-public class ClusterDefinition {
-
- private Set<NodeInfo> nodes;
- private String ipPrefix;
-
- /**
- * Creates a new cluster definition.
- * @param nodes cluster nodes information
- * @param ipPrefix ip prefix common to all cluster nodes
- * @return cluster definition
- */
- public static ClusterDefinition from(Set<NodeInfo> nodes, String ipPrefix) {
- ClusterDefinition definition = new ClusterDefinition();
- definition.ipPrefix = ipPrefix;
- definition.nodes = ImmutableSet.copyOf(nodes);
- return definition;
- }
-
- /**
- * Returns set of cluster nodes info.
- * @return cluster nodes info
- */
- public Set<NodeInfo> getNodes() {
- return ImmutableSet.copyOf(nodes);
- }
-
- /**
- * Returns ipPrefix in dotted decimal notion.
- * @return ip prefix
- */
- public String getIpPrefix() {
- return ipPrefix;
- }
-} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java
deleted file mode 100644
index 8b0001d8..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.cluster.impl;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-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.Service;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cluster.ClusterDefinitionService;
-import org.onosproject.cluster.ControllerNode;
-import org.onosproject.cluster.DefaultControllerNode;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.store.consistent.impl.DatabaseDefinition;
-import org.onosproject.store.consistent.impl.DatabaseDefinitionStore;
-import org.slf4j.Logger;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Enumeration;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static java.net.NetworkInterface.getNetworkInterfaces;
-import static java.util.Collections.list;
-import static org.onosproject.cluster.DefaultControllerNode.DEFAULT_PORT;
-import static org.onosproject.store.consistent.impl.DatabaseManager.PARTITION_DEFINITION_FILE;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Implementation of ClusterDefinitionService.
- */
-@Component(immediate = true)
-@Service
-public class ClusterDefinitionManager implements ClusterDefinitionService {
-
- public static final String CLUSTER_DEFINITION_FILE = "../config/cluster.json";
- private static final String ONOS_NIC = "ONOS_NIC";
- private static final Logger log = getLogger(ClusterDefinitionManager.class);
- private ControllerNode localNode;
- private Set<ControllerNode> seedNodes;
-
- @Activate
- public void activate() {
- File clusterDefinitionFile = new File(CLUSTER_DEFINITION_FILE);
- ClusterDefinitionStore clusterDefinitionStore =
- new ClusterDefinitionStore(clusterDefinitionFile.getPath());
-
- if (!clusterDefinitionFile.exists()) {
- createDefaultClusterDefinition(clusterDefinitionStore);
- }
-
- try {
- ClusterDefinition clusterDefinition = clusterDefinitionStore.read();
- establishSelfIdentity(clusterDefinition);
- seedNodes = ImmutableSet
- .copyOf(clusterDefinition.getNodes())
- .stream()
- .filter(n -> !localNode.id().equals(new NodeId(n.getId())))
- .map(n -> new DefaultControllerNode(new NodeId(n.getId()),
- IpAddress.valueOf(n.getIp()),
- n.getTcpPort()))
- .collect(Collectors.toSet());
- } catch (IOException e) {
- throw new IllegalStateException("Failed to read cluster definition.", e);
- }
-
- log.info("Started");
- }
-
- @Deactivate
- public void deactivate() {
- log.info("Stopped");
- }
-
- @Override
- public ControllerNode localNode() {
- return localNode;
- }
-
- @Override
- public Set<ControllerNode> seedNodes() {
- return seedNodes;
- }
-
- @Override
- public void formCluster(Set<ControllerNode> nodes, String ipPrefix) {
- try {
- Set<NodeInfo> infos = Sets.newHashSet();
- nodes.forEach(n -> infos.add(NodeInfo.from(n.id().toString(),
- n.ip().toString(),
- n.tcpPort())));
-
- ClusterDefinition cdef = ClusterDefinition.from(infos, ipPrefix);
- new ClusterDefinitionStore(CLUSTER_DEFINITION_FILE).write(cdef);
-
- DatabaseDefinition ddef = DatabaseDefinition.from(infos);
- new DatabaseDefinitionStore(PARTITION_DEFINITION_FILE).write(ddef);
- } catch (IOException e) {
- log.error("Unable to form cluster", e);
- }
- }
-
- private IpAddress findLocalIp(ClusterDefinition clusterDefinition) throws SocketException {
- Enumeration<NetworkInterface> interfaces =
- NetworkInterface.getNetworkInterfaces();
- while (interfaces.hasMoreElements()) {
- NetworkInterface iface = interfaces.nextElement();
- Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
- while (inetAddresses.hasMoreElements()) {
- IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
- if (clusterDefinition.getNodes().stream()
- .map(NodeInfo::getIp)
- .map(IpAddress::valueOf)
- .anyMatch(nodeIp -> ip.equals(nodeIp))) {
- return ip;
- }
- }
- }
- throw new IllegalStateException("Unable to determine local ip");
- }
-
- private void establishSelfIdentity(ClusterDefinition clusterDefinition) {
- try {
- IpAddress ip = findLocalIp(clusterDefinition);
- localNode = new DefaultControllerNode(new NodeId(ip.toString()), ip);
- } catch (SocketException e) {
- throw new IllegalStateException("Cannot determine local IP", e);
- }
- }
-
- private void createDefaultClusterDefinition(ClusterDefinitionStore store) {
- // Assumes IPv4 is returned.
- String ip = getSiteLocalAddress();
- String ipPrefix = ip.replaceFirst("\\.[0-9]*$", ".*");
- NodeInfo node = NodeInfo.from(ip, ip, DEFAULT_PORT);
- try {
- store.write(ClusterDefinition.from(ImmutableSet.of(node), ipPrefix));
- } catch (IOException e) {
- log.warn("Unable to write default cluster definition", e);
- }
- }
-
- /**
- * Returns the address that matches the IP prefix given in ONOS_NIC
- * environment variable if one was specified, or the first site local
- * address if one can be found or the loopback address otherwise.
- *
- * @return site-local address in string form
- */
- public static String getSiteLocalAddress() {
- try {
- String ipPrefix = System.getenv(ONOS_NIC);
- for (NetworkInterface nif : list(getNetworkInterfaces())) {
- for (InetAddress address : list(nif.getInetAddresses())) {
- IpAddress ip = IpAddress.valueOf(address);
- if (ipPrefix == null && address.isSiteLocalAddress() ||
- ipPrefix != null && matchInterface(ip.toString(), ipPrefix)) {
- return ip.toString();
- }
- }
- }
- } catch (SocketException e) {
- log.error("Unable to get network interfaces", e);
- }
-
- return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString();
- }
-
- // Indicates whether the specified interface address matches the given prefix.
- // FIXME: Add a facility to IpPrefix to make this more robust
- private static boolean matchInterface(String ip, String ipPrefix) {
- String s = ipPrefix.replaceAll("\\.\\*", "");
- return ip.startsWith(s);
- }
-}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java
deleted file mode 100644
index 2a2f4dc4..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2014-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.cluster.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.io.Files;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Allows for reading and writing cluster definition as a JSON file.
- */
-public class ClusterDefinitionStore {
-
- private final File file;
-
- /**
- * Creates a reader/writer of the cluster definition file.
- * @param filePath location of the definition file
- */
- public ClusterDefinitionStore(String filePath) {
- file = new File(filePath);
- }
-
- /**
- * Returns the cluster definition.
- * @return cluster definition
- * @throws IOException when I/O exception of some sort has occurred
- */
- public ClusterDefinition read() throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- return mapper.readValue(file, ClusterDefinition.class);
- }
-
- /**
- * Writes the specified cluster definition to file.
- * @param definition cluster definition
- * @throws IOException when I/O exception of some sort has occurred
- */
- public void write(ClusterDefinition definition) throws IOException {
- checkNotNull(definition);
- // write back to file
- Files.createParentDirs(file);
- ObjectMapper mapper = new ObjectMapper();
- mapper.writeValue(file, definition);
- }
-}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
index 859efebf..3bb6a708 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
@@ -27,8 +27,8 @@ import org.apache.felix.scr.annotations.Service;
import org.joda.time.DateTime;
import org.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.ClusterDefinitionService;
import org.onosproject.cluster.ClusterEvent;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterStore;
import org.onosproject.cluster.ClusterStoreDelegate;
import org.onosproject.cluster.ControllerNode;
@@ -99,14 +99,14 @@ public class DistributedClusterStore
private ControllerNode localNode;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MessagingService messagingService;
@Activate
public void activate() {
- localNode = clusterDefinitionService.localNode();
+ localNode = clusterMetadataService.getLocalNode();
messagingService.registerHandler(HEARTBEAT_MESSAGE,
new HeartbeatMessageHandler(), heartBeatMessageHandler);
@@ -116,9 +116,6 @@ public class DistributedClusterStore
heartBeatSender.scheduleWithFixedDelay(this::heartbeat, 0,
HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS);
- addNode(localNode);
- updateState(localNode.id(), State.ACTIVE);
-
log.info("Started");
}
@@ -188,7 +185,7 @@ public class DistributedClusterStore
private void addNode(ControllerNode node) {
allNodes.put(node.id(), node);
- updateState(node.id(), State.INACTIVE);
+ updateState(node.id(), node.equals(localNode) ? State.ACTIVE : State.INACTIVE);
notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_ADDED, node));
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java
new file mode 100644
index 00000000..9f6c4130
--- /dev/null
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java
@@ -0,0 +1,221 @@
+package org.onosproject.store.cluster.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.net.NetworkInterface.getNetworkInterfaces;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+
+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.Service;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataStore;
+import org.onosproject.cluster.ClusterMetadataStoreDelegate;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.DefaultControllerNode;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.Partition;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.service.Versioned;
+import org.slf4j.Logger;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+/**
+ * ClusterMetadataStore backed by a local file.
+ */
+@Component(immediate = true, enabled = true)
+@Service
+public class StaticClusterMetadataStore
+ extends AbstractStore<ClusterMetadataEvent, ClusterMetadataStoreDelegate>
+ implements ClusterMetadataStore {
+
+ private final Logger log = getLogger(getClass());
+ private static final String CLUSTER_METADATA_FILE = "../config/cluster.json";
+ private static final int DEFAULT_ONOS_PORT = 9876;
+ private final File metadataFile = new File(CLUSTER_METADATA_FILE);
+ private AtomicReference<ClusterMetadata> metadata = new AtomicReference<>();
+ private ObjectMapper mapper;
+ private long version;
+
+ @Activate
+ public void activate() {
+ mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule();
+ module.addSerializer(NodeId.class, new NodeIdSerializer());
+ module.addDeserializer(NodeId.class, new NodeIdDeserializer());
+ module.addSerializer(ControllerNode.class, new ControllerNodeSerializer());
+ module.addDeserializer(ControllerNode.class, new ControllerNodeDeserializer());
+ mapper.registerModule(module);
+ File metadataFile = new File(CLUSTER_METADATA_FILE);
+ if (metadataFile.exists()) {
+ try {
+ metadata.set(mapper.readValue(metadataFile, ClusterMetadata.class));
+ version = metadataFile.lastModified();
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ }
+ } else {
+ String localIp = getSiteLocalAddress();
+ ControllerNode localNode =
+ new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT);
+ metadata.set(ClusterMetadata.builder()
+ .withName("default")
+ .withControllerNodes(Arrays.asList(localNode))
+ .withPartitions(Lists.newArrayList(new Partition("p1", Lists.newArrayList(localNode.id()))))
+ .build());
+ version = System.currentTimeMillis();
+ }
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public void setDelegate(ClusterMetadataStoreDelegate delegate) {
+ checkNotNull(delegate, "Delegate cannot be null");
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void unsetDelegate(ClusterMetadataStoreDelegate delegate) {
+ this.delegate = null;
+ }
+
+ @Override
+ public boolean hasDelegate() {
+ return this.delegate != null;
+ }
+
+ @Override
+ public Versioned<ClusterMetadata> getClusterMetadata() {
+ return new Versioned<>(metadata.get(), version);
+ }
+
+ @Override
+ public void setClusterMetadata(ClusterMetadata metadata) {
+ checkNotNull(metadata);
+ try {
+ Files.createParentDirs(metadataFile);
+ mapper.writeValue(metadataFile, metadata);
+ this.metadata.set(metadata);
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ }
+ }
+
+ @Override
+ public void setActiveReplica(String partitionId, NodeId nodeId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unsetActiveReplica(String partitionId, NodeId nodeId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Collection<NodeId> getActiveReplicas(String partitionId) {
+ return metadata.get().getPartitions()
+ .stream()
+ .filter(r -> r.getName().equals(partitionId))
+ .findFirst()
+ .map(r -> r.getMembers())
+ .orElse(null);
+ }
+
+ private static class ControllerNodeSerializer extends JsonSerializer<ControllerNode> {
+ @Override
+ public void serialize(ControllerNode node, JsonGenerator jgen, SerializerProvider provider)
+ throws IOException, JsonProcessingException {
+ jgen.writeStartObject();
+ jgen.writeStringField("id", node.id().toString());
+ jgen.writeStringField("ip", node.ip().toString());
+ jgen.writeNumberField("port", node.tcpPort());
+ jgen.writeEndObject();
+ }
+ }
+
+ private static class ControllerNodeDeserializer extends JsonDeserializer<ControllerNode> {
+ @Override
+ public ControllerNode deserialize(JsonParser jp, DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+ JsonNode node = jp.getCodec().readTree(jp);
+ NodeId nodeId = new NodeId(node.get("id").textValue());
+ IpAddress ip = IpAddress.valueOf(node.get("ip").textValue());
+ int port = node.get("port").asInt();
+ return new DefaultControllerNode(nodeId, ip, port);
+ }
+ }
+
+ private static class NodeIdSerializer extends JsonSerializer<NodeId> {
+ @Override
+ public void serialize(NodeId nodeId, JsonGenerator jgen, SerializerProvider provider)
+ throws IOException, JsonProcessingException {
+ jgen.writeString(nodeId.toString());
+ }
+ }
+
+ private class NodeIdDeserializer extends JsonDeserializer<NodeId> {
+ @Override
+ public NodeId deserialize(JsonParser jp, DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+ JsonNode node = jp.getCodec().readTree(jp);
+ return new NodeId(node.asText());
+ }
+ }
+
+
+ private static String getSiteLocalAddress() {
+ Function<NetworkInterface, IpAddress> ipLookup = nif -> {
+ for (InetAddress address : Collections.list(nif.getInetAddresses())) {
+ if (address.isSiteLocalAddress()) {
+ return IpAddress.valueOf(address);
+ }
+ }
+ return null;
+ };
+ try {
+ IpAddress ip = ipLookup.apply(NetworkInterface.getByName("eth0"));
+ if (ip != null) {
+ return ip.toString();
+ }
+ for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
+ ip = ipLookup.apply(nif);
+ if (ip != null) {
+ return ip.toString();
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Unable to get network interfaces", e);
+ }
+ return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java
index ffdd25f2..ddb45f71 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java
@@ -22,7 +22,7 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.nio.service.IOLoopMessaging;
-import org.onosproject.cluster.ClusterDefinitionService;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.cluster.messaging.Endpoint;
import org.slf4j.Logger;
@@ -38,11 +38,11 @@ public class IOLoopMessagingManager extends IOLoopMessaging {
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Activate
public void activate() throws Exception {
- ControllerNode localNode = clusterDefinitionService.localNode();
+ ControllerNode localNode = clusterMetadataService.getLocalNode();
super.start(new Endpoint(localNode.ip(), localNode.tcpPort()));
log.info("Started");
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
index 9328817b..23c81869 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
@@ -16,6 +16,7 @@
package org.onosproject.store.cluster.messaging.impl;
import com.google.common.base.Strings;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -23,7 +24,7 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.netty.NettyMessaging;
-import org.onosproject.cluster.ClusterDefinitionService;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.cluster.messaging.Endpoint;
import org.slf4j.Logger;
@@ -41,11 +42,11 @@ public class NettyMessagingManager extends NettyMessaging {
private static final short MIN_KS_LENGTH = 6;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Activate
public void activate() throws Exception {
- ControllerNode localNode = clusterDefinitionService.localNode();
+ ControllerNode localNode = clusterMetadataService.getLocalNode();
getTLSParameters();
super.start(new Endpoint(localNode.ip(), localNode.tcpPort()));
log.info("Started");
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java
deleted file mode 100644
index 11b56c14..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.consistent.impl;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import org.onosproject.store.cluster.impl.NodeInfo;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Partitioned database configuration.
- */
-public class DatabaseDefinition {
- private Map<String, Set<NodeInfo>> partitions;
- private Set<NodeInfo> nodes;
-
- /**
- * Creates a new DatabaseDefinition.
- *
- * @param partitions partition map
- * @param nodes set of nodes
- * @return database definition
- */
- public static DatabaseDefinition from(Map<String, Set<NodeInfo>> partitions,
- Set<NodeInfo> nodes) {
- checkNotNull(partitions);
- checkNotNull(nodes);
- DatabaseDefinition definition = new DatabaseDefinition();
- definition.partitions = ImmutableMap.copyOf(partitions);
- definition.nodes = ImmutableSet.copyOf(nodes);
- return definition;
- }
-
- /**
- * Creates a new DatabaseDefinition using default partitions.
- *
- * @param nodes set of nodes
- * @return database definition
- */
- public static DatabaseDefinition from(Set<NodeInfo> nodes) {
- return from(generateDefaultPartitions(nodes), nodes);
- }
-
- /**
- * Returns the map of database partitions.
- *
- * @return db partition map
- */
- public Map<String, Set<NodeInfo>> getPartitions() {
- return partitions;
- }
-
- /**
- * Returns the set of nodes.
- *
- * @return nodes
- */
- public Set<NodeInfo> getNodes() {
- return nodes;
- }
-
-
- /**
- * Generates set of default partitions using permutations of the nodes.
- *
- * @param nodes information about cluster nodes
- * @return default partition map
- */
- private static Map<String, Set<NodeInfo>> generateDefaultPartitions(Set<NodeInfo> nodes) {
- List<NodeInfo> sorted = new ArrayList<>(nodes);
- Collections.sort(sorted, (o1, o2) -> o1.getId().compareTo(o2.getId()));
- Map<String, Set<NodeInfo>> partitions = Maps.newHashMap();
-
- int length = nodes.size();
- int count = 3;
- for (int i = 0; i < length; i++) {
- Set<NodeInfo> set = new HashSet<>(count);
- for (int j = 0; j < count; j++) {
- set.add(sorted.get((i + j) % length));
- }
- partitions.put("p" + (i + 1), set);
- }
- return partitions;
- }
-
-} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java
deleted file mode 100644
index b77667b2..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.consistent.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import java.io.File;
-import java.io.IOException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.io.Files;
-
-/**
- * Allows for reading and writing partitioned database definition as a JSON file.
- */
-public class DatabaseDefinitionStore {
-
- private final File file;
-
- /**
- * Creates a reader/writer of the database definition file.
- *
- * @param filePath location of the definition file
- */
- public DatabaseDefinitionStore(String filePath) {
- file = new File(checkNotNull(filePath));
- }
-
- /**
- * Creates a reader/writer of the database definition file.
- *
- * @param filePath location of the definition file
- */
- public DatabaseDefinitionStore(File filePath) {
- file = checkNotNull(filePath);
- }
-
- /**
- * Returns the database definition.
- *
- * @return database definition
- * @throws IOException when I/O exception of some sort has occurred.
- */
- public DatabaseDefinition read() throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- return mapper.readValue(file, DatabaseDefinition.class);
- }
-
- /**
- * Writes the specified database definition to file.
- *
- * @param definition database definition
- * @throws IOException when I/O exception of some sort has occurred.
- */
- public void write(DatabaseDefinition definition) throws IOException {
- checkNotNull(definition);
- // write back to file
- Files.createParentDirs(file);
- ObjectMapper mapper = new ObjectMapper();
- mapper.writeValue(file, definition);
- }
-}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java
index 6ea7c220..3e89635a 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java
@@ -18,7 +18,6 @@ package org.onosproject.store.consistent.impl;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
@@ -50,12 +49,12 @@ import org.apache.felix.scr.annotations.Service;
import org.onosproject.app.ApplicationEvent;
import org.onosproject.app.ApplicationListener;
import org.onosproject.app.ApplicationService;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.IdGenerator;
-import org.onosproject.store.cluster.impl.ClusterDefinitionManager;
-import org.onosproject.store.cluster.impl.NodeInfo;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.ecmap.EventuallyConsistentMapBuilderImpl;
import org.onosproject.store.service.AtomicCounterBuilder;
@@ -73,8 +72,6 @@ import org.onosproject.store.service.Transaction;
import org.onosproject.store.service.TransactionContextBuilder;
import org.slf4j.Logger;
-import java.io.File;
-import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -99,8 +96,6 @@ public class DatabaseManager implements StorageService, StorageAdminService {
private final Logger log = getLogger(getClass());
- public static final int COPYCAT_TCP_PORT = 9876;
- public static final String PARTITION_DEFINITION_FILE = "../config/tablets.json";
public static final String BASE_PARTITION_NAME = "p0";
private static final int RAFT_ELECTION_TIMEOUT_MILLIS = 3000;
@@ -122,6 +117,9 @@ public class DatabaseManager implements StorageService, StorageAdminService {
Multimaps.synchronizedMultimap(ArrayListMultimap.create());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterMetadataService clusterMetadataService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
@@ -130,8 +128,9 @@ public class DatabaseManager implements StorageService, StorageAdminService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterCommunicationService clusterCommunicator;
- protected String nodeToUri(NodeInfo node) {
- return String.format("onos://%s:%d", node.getIp(), node.getTcpPort());
+ protected String nodeIdToUri(NodeId nodeId) {
+ ControllerNode node = clusterService.getNode(nodeId);
+ return String.format("onos://%s:%d", node.ip(), node.tcpPort());
}
protected void bindApplicationService(ApplicationService service) {
@@ -147,30 +146,22 @@ public class DatabaseManager implements StorageService, StorageAdminService {
@Activate
public void activate() {
localNodeId = clusterService.getLocalNode().id();
- // load database configuration
- File databaseDefFile = new File(PARTITION_DEFINITION_FILE);
- log.info("Loading database definition: {}", databaseDefFile.getAbsolutePath());
- Map<String, Set<NodeInfo>> partitionMap;
- try {
- DatabaseDefinitionStore databaseDefStore = new DatabaseDefinitionStore(databaseDefFile);
- if (!databaseDefFile.exists()) {
- createDefaultDatabaseDefinition(databaseDefStore);
- }
- partitionMap = databaseDefStore.read().getPartitions();
- } catch (IOException e) {
- throw new IllegalStateException("Failed to load database config", e);
- }
+ Map<String, Set<NodeId>> partitionMap = Maps.newHashMap();
+ clusterMetadataService.getClusterMetadata().getPartitions().forEach(p -> {
+ partitionMap.put(p.getName(), Sets.newHashSet(p.getMembers()));
+ });
+
String[] activeNodeUris = partitionMap.values()
.stream()
.reduce((s1, s2) -> Sets.union(s1, s2))
.get()
.stream()
- .map(this::nodeToUri)
+ .map(this::nodeIdToUri)
.toArray(String[]::new);
- String localNodeUri = nodeToUri(NodeInfo.of(clusterService.getLocalNode()));
+ String localNodeUri = nodeIdToUri(clusterMetadataService.getLocalNode().id());
Protocol protocol = new CopycatCommunicationProtocol(clusterService, clusterCommunicator);
ClusterConfig clusterConfig = new ClusterConfig()
@@ -198,7 +189,7 @@ public class DatabaseManager implements StorageService, StorageAdminService {
List<Database> partitions = partitionMap.entrySet()
.stream()
.map(entry -> {
- String[] replicas = entry.getValue().stream().map(this::nodeToUri).toArray(String[]::new);
+ String[] replicas = entry.getValue().stream().map(this::nodeIdToUri).toArray(String[]::new);
return newDatabaseConfig(entry.getKey(), newPersistentLog(), replicas);
})
.map(config -> {
@@ -229,17 +220,6 @@ public class DatabaseManager implements StorageService, StorageAdminService {
log.info("Started");
}
- private void createDefaultDatabaseDefinition(DatabaseDefinitionStore store) {
- // Assumes IPv4 is returned.
- String ip = ClusterDefinitionManager.getSiteLocalAddress();
- NodeInfo node = NodeInfo.from(ip, ip, COPYCAT_TCP_PORT);
- try {
- store.write(DatabaseDefinition.from(ImmutableSet.of(node)));
- } catch (IOException e) {
- log.warn("Unable to write default cluster definition", e);
- }
- }
-
@Deactivate
public void deactivate() {
CompletableFuture.allOf(inMemoryDatabase.close(), partitionedDatabase.close())
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
index b66f424b..73888221 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
@@ -86,7 +86,7 @@ public class DefaultTransactionContext implements TransactionContext {
@SuppressWarnings("unchecked")
@Override
- public void commit() {
+ public boolean commit() {
// TODO: rework commit implementation to be more intuitive
checkState(isOpen, TX_NOT_OPEN_ERROR);
CommitResponse response = null;
@@ -95,10 +95,11 @@ public class DefaultTransactionContext implements TransactionContext {
txMaps.values().forEach(m -> updates.addAll(m.prepareDatabaseUpdates()));
Transaction transaction = new DefaultTransaction(transactionId, updates);
response = Futures.getUnchecked(database.prepareAndCommit(transaction));
+ return response.success();
+ } catch (Exception e) {
+ abort();
+ return false;
} finally {
- if (response != null && !response.success()) {
- abort();
- }
isOpen = false;
}
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
index 973db494..687762e0 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
@@ -427,6 +427,7 @@ public class GossipDeviceStore
// Primary providers can respond to all changes, but ancillary ones
// should respond only to annotation changes.
+ DeviceEvent event = null;
if ((providerId.isAncillary() && annotationsChanged) ||
(!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) {
boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice);
@@ -436,17 +437,18 @@ public class GossipDeviceStore
providerId, oldDevice, devices.get(newDevice.id())
, newDevice);
}
- if (!providerId.isAncillary()) {
- boolean wasOnline = availableDevices.contains(newDevice.id());
- markOnline(newDevice.id(), newTimestamp);
- if (!wasOnline) {
- notifyDelegateIfNotNull(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null));
- }
- }
- return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null);
+ event = new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null);
}
- return null;
+
+ if (!providerId.isAncillary()) {
+ boolean wasOnline = availableDevices.contains(newDevice.id());
+ markOnline(newDevice.id(), newTimestamp);
+ if (!wasOnline) {
+ notifyDelegateIfNotNull(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null));
+ }
+ }
+ return event;
}
@Override
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java
index e62a2d5c..f5ce47fc 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java
@@ -100,4 +100,4 @@ class MapDbPersistentStore<K, V> implements PersistentStore<K, V> {
items.remove(keyBytes);
database.commit();
}
-}
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
index 10f79eb0..687576c3 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
@@ -52,7 +52,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Implementation of ResourceStore using TransactionalMap.
*/
-@Component(immediate = true, enabled = false)
+@Component(immediate = true)
@Service
@Beta
public class ConsistentResourceStore implements ResourceStore {
@@ -239,6 +239,18 @@ public class ConsistentResourceStore implements ResourceStore {
}
@Override
+ public Collection<ResourcePath> getChildResources(ResourcePath parent) {
+ checkNotNull(parent);
+
+ Versioned<List<ResourcePath>> children = childMap.get(parent);
+ if (children == null) {
+ return Collections.emptyList();
+ }
+
+ return children.value();
+ }
+
+ @Override
public <T> Collection<ResourcePath> getAllocatedResources(ResourcePath parent, Class<T> cls) {
checkNotNull(parent);
checkNotNull(cls);
diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java
index 25e23d3a..61d1937e 100644
--- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java
+++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java
@@ -325,5 +325,11 @@ public class PartitionManagerTest {
return Objects.equals(this.hash(), that.hash());
}
+
+ @Override
+ public int compareTo(Key o) {
+ Long thisHash = hash();
+ return thisHash.compareTo(o.hash());
+ }
}
}
diff --git a/framework/src/onos/core/store/persistence/pom.xml b/framework/src/onos/core/store/persistence/pom.xml
new file mode 100644
index 00000000..555de11a
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <repositories>
+ <repository>
+ <id>repository.springsource.com.release</id>
+ <name>SpringSource OBR - Release</name>
+ <url>http://repository.springsource.com/maven/bundles/release</url>
+ </repository>
+ <repository>
+ <id>repository.springsource.com.external</id>
+ <name>SpringSource OBR - External</name>
+ <url>http://repository.springsource.com/maven/bundles/external</url>
+ </repository>
+ </repositories>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-store</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-core-persistence</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>ONOS Core persistent local store subsystem</description>
+
+
+
+ <dependencies>
+ <!--<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>-->
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mapdb</groupId>
+ <artifactId>mapdb</artifactId>
+ <version>1.0.8</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java
new file mode 100644
index 00000000..88c7d148
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * 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.persistence.impl;
+
+import org.mapdb.DB;
+import org.onosproject.persistence.PersistentMapBuilder;
+import org.onosproject.store.service.Serializer;
+
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default builder for persistent maps stored in the mapDB local database via the persistence service.
+ */
+public class DefaultPersistentMapBuilder<K, V> implements PersistentMapBuilder<K, V> {
+
+ private final DB localDB;
+
+ private String name = null;
+
+ private Serializer serializer = null;
+
+
+ public DefaultPersistentMapBuilder(DB localDB) {
+ checkNotNull(localDB, "The local database cannot be null.");
+ this.localDB = localDB;
+ }
+
+ public PersistentMapBuilder<K, V> withName(String name) {
+ this.name = PersistenceManager.MAP_PREFIX + checkNotNull(name);
+ return this;
+ }
+
+ public PersistentMapBuilder<K, V> withSerializer(Serializer serializer) {
+ checkArgument(this.serializer == null);
+ checkNotNull(serializer);
+ this.serializer = serializer;
+ return this;
+ }
+
+ public Map<K, V> build() {
+ checkNotNull(name, "The name must be assigned.");
+ checkNotNull(serializer, "The key serializer must be assigned.");
+
+ return new PersistentMap<K, V>(serializer, localDB, name);
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java
new file mode 100644
index 00000000..e1544fb4
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.persistence.impl;
+
+import org.mapdb.DB;
+import org.onosproject.persistence.PersistentSetBuilder;
+import org.onosproject.store.service.Serializer;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default builder for persistent sets stored in the mapDB local database via the persistence service..
+ */
+public class DefaultPersistentSetBuilder<E> implements PersistentSetBuilder<E> {
+
+ private final DB localDB;
+
+ private String name = null;
+
+ private Serializer serializer = null;
+
+ public DefaultPersistentSetBuilder(DB localDB) {
+ this.localDB = checkNotNull(localDB, "The local database cannot be null.");
+ }
+
+ public PersistentSetBuilder<E> withName(String name) {
+ this.name = PersistenceManager.SET_PREFIX + checkNotNull(name);
+ return this;
+ }
+
+ public PersistentSetBuilder<E> withSerializer(Serializer serializer) {
+ checkArgument(this.serializer == null);
+ checkNotNull(serializer);
+ this.serializer = serializer;
+ return this;
+ }
+
+ public PersistentSet<E> build() {
+ checkNotNull(name, "The name must be assigned.");
+ checkNotNull(serializer, "The serializer must be assigned.");
+
+ return new PersistentSet<E>(serializer, localDB, name);
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java
new file mode 100644
index 00000000..f2ba20c2
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.persistence.impl;
+
+/**
+ * An exception defined for failures of the local persistent store system.
+ */
+
+/**
+ * Throws an exception with the specified message.
+ */
+public class PersistenceException extends RuntimeException {
+ public PersistenceException(String s) {
+ super(s);
+ }
+}
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
new file mode 100644
index 00000000..64a8683a
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
@@ -0,0 +1,138 @@
+/*
+ * 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.persistence.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.Service;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.PersistenceService;
+import org.onosproject.persistence.PersistentMapBuilder;
+import org.onosproject.persistence.PersistentSetBuilder;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Service that maintains local disk backed maps and sets. This implementation automatically deletes empty structures
+ * on shutdown.
+ */
+@Component(immediate = true)
+@Service
+public class PersistenceManager implements PersistenceService {
+
+ private static final String DATABASE_PATH = "../data/localDB";
+
+ private static final String ENCLOSING_FOLDER = "../data";
+
+ static final String MAP_PREFIX = "map:";
+
+ static final String SET_PREFIX = "set:";
+
+ private final Logger log = getLogger(getClass());
+
+ private DB localDB = null;
+
+ private static final int FLUSH_FREQUENCY_MILLIS = 3000;
+
+ private final Timer timer = new Timer();
+
+ private final CommitTask commitTask = new CommitTask();
+
+ @Activate
+ public void activate() {
+ Path dbPath = Paths.get(DATABASE_PATH);
+ Path dbFolderPath = Paths.get(ENCLOSING_FOLDER);
+ //Make sure the directory exists, if it does not, make it.
+ if (!dbFolderPath.toFile().isDirectory()) {
+ log.info("The specified folder location for the database did not exist and will be created.");
+ try {
+ Files.createDirectories(dbFolderPath);
+ } catch (IOException e) {
+ log.error("Could not create the required folder for the database.");
+ throw new PersistenceException("Database folder could not be created.");
+ }
+ }
+ //Notify if the database file does not exist.
+ boolean dbFound = Files.exists(dbPath);
+ if (!dbFound) {
+ log.info("The database file could not be located, a new database will be constructed.");
+
+ } else {
+ log.info("A previous database file has been found.");
+ }
+ localDB = DBMaker.newFileDB(dbPath.toFile())
+ .asyncWriteEnable()
+ .closeOnJvmShutdown()
+ .make();
+ timer.schedule(commitTask, FLUSH_FREQUENCY_MILLIS, FLUSH_FREQUENCY_MILLIS);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ for (Map.Entry<String, Object> entry : localDB.getAll().entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ //This is a map implementation to be handled as such
+ if (value instanceof Map) {
+ Map asMap = (Map) value;
+ if (asMap.isEmpty()) {
+ //the map is empty and may be deleted
+ localDB.delete(key);
+ }
+ //This is a set implementation and can be handled as such
+ } else if (value instanceof Set) {
+ Set asSet = (Set) value;
+ if (asSet.isEmpty()) {
+ //the set is empty and may be deleted
+ localDB.delete(key);
+ }
+ }
+ }
+ localDB.commit();
+ localDB.close();
+ log.info("Stopped");
+ }
+
+ public <K, V> PersistentMapBuilder<K, V> persistentMapBuilder() {
+ return new DefaultPersistentMapBuilder<>(localDB);
+ }
+
+ public <E> PersistentSetBuilder<E> persistentSetBuilder() {
+ return new DefaultPersistentSetBuilder<>(localDB);
+ }
+
+ private class CommitTask extends TimerTask {
+
+ @Override
+ public void run() {
+ localDB.commit();
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java
new file mode 100644
index 00000000..4506bbda
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java
@@ -0,0 +1,192 @@
+/*
+ * 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.persistence.impl;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.mapdb.DB;
+import org.mapdb.Hasher;
+import org.onosproject.store.service.Serializer;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+/**
+ * A map implementation that stores and receives all data from a serialized internal map.
+ */
+public class PersistentMap<K, V> implements Map<K, V> {
+
+ private final Serializer serializer;
+
+ private final org.mapdb.DB database;
+
+ private final Map<byte[], byte[]> items;
+
+ private final String name;
+
+ public PersistentMap(Serializer serializer, DB database, String name) {
+ this.serializer = checkNotNull(serializer);
+ this.database = checkNotNull(database);
+ this.name = checkNotNull(name);
+
+ items = database
+ .createHashMap(name)
+ .keySerializer(org.mapdb.Serializer.BYTE_ARRAY)
+ .valueSerializer(org.mapdb.Serializer.BYTE_ARRAY)
+ .hasher(Hasher.BYTE_ARRAY)
+ .makeOrGet();
+ }
+
+ /**
+ * Reads this set in deserialized form into the provided map.
+ *
+ * @param items the map to be populated
+ */
+ public void readInto(Map<K, V> items) {
+ this.items.forEach((keyBytes, valueBytes) ->
+ items.put(serializer.decode(keyBytes),
+ serializer.decode(valueBytes)));
+ }
+
+ @Override
+ public V remove(Object key) {
+ checkNotNull(key, "Key can not be null.");
+ V removed = get(key);
+ items.remove(serializer.encode(key));
+ return removed;
+ }
+
+ @Override
+ public int size() {
+ return items.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return items.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ checkNotNull(key, "Key cannot be null.");
+ return items.containsKey(serializer.encode(key));
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ checkNotNull(value, "Value cannot be null.");
+ byte[] serialized = serializer.encode(value);
+ for (byte[] compareValue : items.values()) {
+ boolean same = true;
+ if (compareValue == null) {
+ same = false;
+ } else if (compareValue.length != serialized.length) {
+ same = false;
+ } else {
+ for (int i = 0; i < serialized.length; i++) {
+ if (serialized[i] != compareValue[i]) {
+ same = false;
+ break;
+ }
+ }
+ }
+ if (same) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public V get(Object key) {
+ checkNotNull(key, "Key cannot be null.");
+ return serializer.decode(items.get(serializer.encode(key)));
+ }
+
+ @Override
+ public V put(K key, V value) {
+ checkNotNull(key, "Key cannot be null.");
+ checkNotNull(value, "Value cannot be null.");
+ byte[] prevVal = items.put(serializer.encode(key), serializer.encode(value));
+ if (prevVal == null) {
+ return null;
+ }
+ return serializer.decode(prevVal);
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ checkNotNull(m, "The passed in map cannot be null.");
+ m.forEach((k, v) -> items.put(serializer.encode(k), serializer.encode(v)));
+ }
+
+ @Override
+ public void clear() {
+ items.clear();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ Set<K> keys = Sets.newHashSet();
+ items.keySet().forEach(k -> keys.add(serializer.decode(k)));
+ return keys;
+ }
+
+ @Override
+ public Collection<V> values() {
+ Collection<V> values = Sets.newHashSet();
+ items.values().forEach(v -> values.add(serializer.decode(v)));
+ return values;
+ }
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ Set<Entry<K, V>> entries = Sets.newHashSet();
+ items.entrySet().
+ forEach(e -> entries.add(Maps.immutableEntry(serializer.decode(e.getKey()),
+ serializer.decode(e.getValue()))));
+ return entries;
+ }
+
+ @Override
+ public boolean equals(Object map) {
+ //This is not threadsafe and on larger maps incurs a significant processing cost
+ if (!(map instanceof Map)) {
+ return false;
+ }
+ Map asMap = (Map) map;
+ if (this.size() != asMap.size()) {
+ return false;
+ }
+ for (Entry entry : this.entrySet()) {
+ Object key = entry.getKey();
+ if (!asMap.containsKey(key) || !asMap.get(key).equals(entry.getValue())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java
new file mode 100644
index 00000000..26118cf6
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java
@@ -0,0 +1,194 @@
+/*
+ * 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.persistence.impl;
+
+import com.google.common.collect.Iterators;
+import org.mapdb.DB;
+import org.mapdb.Hasher;
+import org.mapdb.Serializer;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A set implementation that gets and receives all data from a serialized internal set.
+ */
+//TODO add locking for reads and writes
+public class PersistentSet<E> implements Set<E> {
+
+ private final org.onosproject.store.service.Serializer serializer;
+
+ private final org.mapdb.DB database;
+
+ private final Set<byte[]> items;
+
+ private final String name;
+
+ public PersistentSet(org.onosproject.store.service.Serializer serializer, DB database, String name) {
+ this.serializer = checkNotNull(serializer);
+ this.database = checkNotNull(database);
+ this.name = checkNotNull(name);
+
+ items = database
+ .createHashSet(name)
+ .serializer(Serializer.BYTE_ARRAY)
+ .hasher(Hasher.BYTE_ARRAY)
+ .makeOrGet();
+ }
+
+ public void readInto(Set<E> items) {
+ this.items.forEach(item -> items.add(serializer.decode(item)));
+ }
+
+ @Override
+ public int size() {
+ return items.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return items.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ checkNotNull(o, "The argument cannot be null");
+ return items.contains(serializer.encode(o));
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return Iterators.transform(items.iterator(), serializer::decode);
+ }
+
+ @Override
+ public Object[] toArray() {
+ Object[] retArray = new Object[items.size()];
+ int index = 0;
+ Iterator<byte[]> iterator = items.iterator();
+ while (iterator.hasNext()) {
+ retArray[index] = serializer.decode(iterator.next());
+ index++;
+ }
+ return retArray;
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ checkNotNull(a, "The passed in array cannot be null.");
+ int index = 0;
+ Iterator<byte[]> iterator = items.iterator();
+ T[] retArray;
+ if (a.length >= items.size()) {
+ retArray = a;
+ } else {
+ retArray = (T[]) new Object[items.size()];
+ }
+ while (iterator.hasNext()) {
+ retArray[index++] = serializer.decode(iterator.next());
+ }
+ if (retArray.length > items.size()) {
+ retArray[index] = null;
+ }
+ return retArray;
+ }
+
+ @Override
+ public boolean add(E item) {
+ checkNotNull("Item to be added cannot be null.");
+ return items.add(serializer.encode(item));
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ checkNotNull(o, "Item to be removed cannot be null.");
+ return items.remove(serializer.encode(o));
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ checkNotNull(c, "Collection cannot be internal.");
+ for (Object item : c) {
+ if (!items.contains(serializer.encode(item))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ checkNotNull(c, "The collection to be added cannot be null.");
+ boolean changed = false;
+ for (Object item : c) {
+ changed = items.add(serializer.encode(item)) || changed;
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ boolean changed = false;
+ for (byte[] item : items) {
+ E deserialized = serializer.decode(item);
+ if (!c.contains(deserialized)) {
+ changed = items.remove(item) || changed;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ boolean changed = false;
+ for (Object item : c) {
+ changed = items.remove(serializer.encode(item)) || changed;
+ }
+ return changed;
+ }
+
+ @Override
+ public void clear() {
+ items.clear();
+ }
+
+ @Override
+ public boolean equals(Object set) {
+ //This is not threadsafe and on larger sets incurs a significant processing cost
+ if (!(set instanceof Set)) {
+ return false;
+ }
+ Set asSet = (Set) set;
+ if (asSet.size() != this.size()) {
+ return false;
+ }
+ for (Object item : this) {
+ if (!asSet.contains(item)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java
new file mode 100644
index 00000000..968a5046
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementations of core persistence classes.
+ */
+package org.onosproject.persistence.impl;
diff --git a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java
new file mode 100644
index 00000000..b059f18e
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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 test;
+
+import com.google.common.collect.Maps;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.impl.PersistentMap;
+import org.onosproject.store.service.Serializer;
+
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test suite for Persistent Map.
+ */
+public class PersistentMapTest {
+
+ private Map<Integer, Integer> map = null;
+ private DB fakeDB = null;
+
+
+ /**
+ * Set up the database, create a map and a direct executor to handle it.
+ *
+ * @throws Exception if instantiation fails
+ */
+ @Before
+ public void setUp() throws Exception {
+ //Creates a db, a map within it and a basic integer serializer (async writing is off)
+ fakeDB = DBMaker
+ .newFileDB(Paths.get("../testDb").toFile())
+ .asyncWriteEnable()
+ .closeOnJvmShutdown()
+ .make();
+ map = new PersistentMap<Integer, Integer>(new Serializer() {
+ @Override
+ public <T> byte[] encode(T object) {
+ if (object == null) {
+ return null;
+ }
+ int num = (Integer) object;
+ byte[] result = new byte[4];
+
+ result[0] = (byte) (num >> 24);
+ result[1] = (byte) (num >> 16);
+ result[2] = (byte) (num >> 8);
+ result[3] = (byte) num;
+ return result;
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ int num = 0x00000000;
+
+ num = num | bytes[0] << 24;
+ num = num | bytes[1] << 16;
+ num = num | bytes[2] << 8;
+ num = num | bytes[3];
+
+ return (T) new java.lang.Integer(num);
+ }
+ }, fakeDB, "map");
+ }
+
+ /**
+ * Clears and deletes the map, closes the datbase and deletes the file.
+ *
+ * @throws Exception if shutdown fails
+ */
+ @After
+ public void tearDown() throws Exception {
+ map.clear();
+ fakeDB.delete("map:map");
+ fakeDB.commit();
+ fakeDB.close();
+ //This is key to prevent artifacts persisting between tests.
+ Paths.get("../testDB").toFile().delete();
+
+
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ //Checks removal and return values
+ fillMap(10);
+ assertEquals(10, map.size());
+ for (int i = 0; i < 10; i++) {
+ assertEquals("The previous value was wrong.", new Integer(i), map.remove(i));
+ assertNull("The previous value was wrong.", map.remove(i));
+ //(i+1) compensates for base zero.
+ assertEquals("The size was wrong.", 10 - (i + 1), map.size());
+ }
+ }
+
+ @Test
+ public void testSize() throws Exception {
+ //Checks size values throughout addition and removal
+ for (int i = 0; i < 10; i++) {
+ map.put(i, i);
+ assertEquals("The map size is wrong.", i + 1, map.size());
+ }
+ for (int i = 0; i < 10; i++) {
+ map.remove(i);
+ assertEquals("The map size is wrong.", 9 - i, map.size());
+ }
+ }
+
+ @Test
+ public void testIsEmpty() throws Exception {
+ //Checks empty condition
+ //asserts that the map starts out empty
+ assertTrue("Map should be empty", map.isEmpty());
+ map.put(1, 1);
+ assertFalse("Map shouldn't be empty.", map.isEmpty());
+ map.remove(1);
+ assertTrue("Map should be empty", map.isEmpty());
+ }
+
+ @Test
+ public void testContains() throws Exception {
+ //Checks both containsKey and containsValue be aware the implementations vary widely (value does not use mapDB
+ //due to object '=='being an insufficient check)
+ for (int i = 0; i < 10; i++) {
+ assertFalse("Map should not contain the key", map.containsKey(i));
+ assertFalse("Map should not contain the value", map.containsValue(i));
+ map.put(i, i);
+ assertTrue("Map should contain the key", map.containsKey(i));
+ assertTrue("Map should contain the value", map.containsValue(i));
+ }
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ //Tests value retrieval and nonexistent key return values
+ for (int i = 0; i < 10; i++) {
+ map.put(i, i);
+ for (int j = 0; j <= i; j++) {
+ assertEquals("The value was wrong.", new Integer(j), map.get(j));
+ }
+ }
+ assertNull("Null return value for nonexistent keys.", map.get(10));
+ }
+
+ @Test
+ public void testPutAll() throws Exception {
+ //Tests adding of an outside map
+ Map<Integer, Integer> testMap = Maps.newHashMap();
+ fillMap(10);
+ map.putAll(testMap);
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The map should contain the current 'i' value.", map.containsKey(i));
+ assertTrue("The map should contain the current 'i' value.", map.containsValue(i));
+ }
+ }
+
+ @Test
+ public void testClear() throws Exception {
+ //Tests clearing the map
+ assertTrue("Map was initialized incorrectly, should be empty.", map.isEmpty());
+ fillMap(10);
+ assertFalse("Map should contain entries now.", map.isEmpty());
+ map.clear();
+ assertTrue("Map should have been cleared of entries.", map.isEmpty());
+
+ }
+
+ @Test
+ public void testKeySet() throws Exception {
+ //Tests key set generation
+ fillMap(10);
+ Set<Integer> keys = map.keySet();
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The key set doesn't contain all keys 0-9", keys.contains(i));
+ }
+ assertEquals("The key set has an incorrect number of entries", 10, keys.size());
+ }
+
+ @Test
+ public void testValues() throws Exception {
+ //Tests value set generation
+ fillMap(10);
+ Set<Integer> values = (Set<Integer>) map.values();
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The key set doesn't contain all keys 0-9", values.contains(i));
+ }
+ assertEquals("The key set has an incorrect number of entries", 10, values.size());
+ }
+
+ @Test
+ public void testEntrySet() throws Exception {
+ //Test entry set generation (violates abstraction by knowing the type of the returned entries)
+ fillMap(10);
+ Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The key set doesn't contain all keys 0-9", entries.contains(Maps.immutableEntry(i, i)));
+ }
+ assertEquals("The key set has an incorrect number of entries", 10, entries.size());
+ }
+
+ @Test public void testPut() throws Exception {
+ //Tests insertion behavior (particularly the returning of previous value)
+ fillMap(10);
+ for (int i = 0; i < 10; i++) {
+ assertEquals("Put should return the previous value", new Integer(i), map.put(i, i + 1));
+ }
+ assertNull(map.put(11, 11));
+ }
+
+ /**
+ * Populated the map with pairs of integers from (0, 0) up to (numEntries - 1, numEntries -1).
+ * @param numEntries number of entries to add
+ */
+ private void fillMap(int numEntries) {
+ for (int i = 0; i < numEntries; i++) {
+ map.put(i, i);
+ }
+ }
+}
diff --git a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java
new file mode 100644
index 00000000..3107ab30
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java
@@ -0,0 +1,274 @@
+/*
+ * 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 test;
+
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.impl.PersistentSet;
+import org.onosproject.store.service.Serializer;
+
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test suite for Persistent Set.
+ */
+public class PersistentSetTest {
+
+ private Set<Integer> set = null;
+ private DB fakeDB = null;
+
+ @Before
+ public void setUp() throws Exception {
+ //Creates a db, a set within it and a basic integer serializer (async writing is off)
+ fakeDB = DBMaker
+ .newFileDB(Paths.get("../testDb").toFile())
+ .asyncWriteEnable()
+ .closeOnJvmShutdown()
+ .make();
+ set = new PersistentSet<Integer>(new Serializer() {
+ @Override
+ public <T> byte[] encode(T object) {
+ if (object == null) {
+ return null;
+ }
+ int num = (Integer) object;
+ byte[] result = new byte[4];
+
+ result[0] = (byte) (num >> 24);
+ result[1] = (byte) (num >> 16);
+ result[2] = (byte) (num >> 8);
+ result[3] = (byte) num;
+ return result;
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ int num = 0x00000000;
+
+ num = num | bytes[0] << 24;
+ num = num | bytes[1] << 16;
+ num = num | bytes[2] << 8;
+ num = num | bytes[3];
+
+ return (T) new java.lang.Integer(num);
+ }
+ }, fakeDB, "set");
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ set.clear();
+ fakeDB.delete("map:map");
+ fakeDB.commit();
+ fakeDB.close();
+ //This is key to prevent artifacts persisting between tests.
+ Paths.get("../testDB").toFile().delete();
+ }
+
+ @Test
+ public void testSize() throws Exception {
+ //Check correct sizing throughout population
+ for (int i = 0; i < 10; i++) {
+ set.add(i);
+ assertEquals("The set should have i + 1 entries.", i + 1, set.size());
+ }
+ }
+
+ @Test
+ public void testIsEmpty() throws Exception {
+ //test empty condition
+ assertTrue("The set should be initialized empty.", set.isEmpty());
+ fillSet(5, this.set);
+ assertFalse("The set should no longer be empty.", set.isEmpty());
+ set.clear();
+ assertTrue("The set should have been cleared.", set.isEmpty());
+ }
+
+ @Test
+ public void testContains() throws Exception {
+ //Test contains
+ assertFalse("The set should not contain anything", set.contains(1));
+ fillSet(10, this.set);
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The set should contain all values 0-9.", set.contains(i));
+ }
+ }
+
+ @Test
+ public void testIterator() throws Exception {
+ //Test iterator behavior (no order guarantees are made)
+ Set<Integer> validationSet = Sets.newHashSet();
+ fillSet(10, this.set);
+ fillSet(10, validationSet);
+ set.iterator().forEachRemaining(item -> assertTrue("Items were mismatched.", validationSet.remove(item)));
+ //All values should have been seen and removed
+ assertTrue("All entries in the validation set should have been removed.", validationSet.isEmpty());
+ }
+
+ @Test
+ public void testToArray() throws Exception {
+ //Test creation of a new array of the values
+ fillSet(10, set);
+ Object[] arr = set.toArray();
+ assertEquals("The array should be of length 10.", 10, arr.length);
+ for (int i = 0; i < 10; i++) {
+ assertTrue("All elements of the array should be in the set.", set.contains((Integer) arr[i]));
+ }
+ }
+
+ @Test
+ public void testToArray1() throws Exception {
+ //Test creation of a new array with the possibility of populating passed array if space allows
+ Integer[] originalArray = new Integer[9];
+ fillSet(9, set);
+ //Test the case where the array and set match in size
+ Object[] retArray = set.toArray(originalArray);
+ assertEquals("If the set can fit the array should be the one passed in.", originalArray, retArray);
+ //Test the case where the passe array is too small to fit the set
+ set.add(9);
+ assertNotEquals("A new set should be generated if the contents will not fit in the passed set",
+ set.toArray(originalArray), originalArray);
+ //Now test the case where there should be a null terminator
+ set.clear();
+ fillSet(5, set);
+ assertNull("The character one after last should be null if the array is larger than the set.",
+ set.toArray(originalArray)[5]);
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ //Test of add
+ for (int i = 0; i < 10; i++) {
+ assertEquals("The size of the set is wrong.", i, set.size());
+ assertTrue("The first add of an element should be true.", set.add(i));
+ assertFalse("The second add of an element should be false.", set.add(i));
+ }
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ //Test removal
+ fillSet(10, set);
+ for (int i = 0; i < 10; i++) {
+ assertEquals("The size of the set is wrong.", 10 - i, set.size());
+ assertTrue("The first removal should be true.", set.remove(i));
+ assertFalse("The second removal should be false (item no longer contained).", set.remove(i));
+ }
+ assertTrue("All elements should have been removed.", set.isEmpty());
+ }
+
+ @Test
+ public void testContainsAll() throws Exception {
+ //Test contains with short circuiting
+ Set<Integer> integersToCheck = Sets.newHashSet();
+ fillSet(10, integersToCheck);
+ fillSet(10, set);
+ assertTrue("The sets should be identical so mutual subsets.", set.containsAll(integersToCheck));
+ set.remove(9);
+ assertFalse("The set should contain one fewer value.", set.containsAll(integersToCheck));
+ }
+
+ @Test
+ public void testAddAll() throws Exception {
+ //Test multi-adds with change checking
+ Set<Integer> integersToCheck = Sets.newHashSet();
+ fillSet(10, integersToCheck);
+ assertFalse("Set should be empty and so integers to check should not be a subset.",
+ set.containsAll(integersToCheck));
+ assertTrue("The set should have changed as a result of add all.", set.addAll(integersToCheck));
+ assertFalse("The set should not have changed as a result of add all a second time.",
+ set.addAll(integersToCheck));
+ assertTrue("The sets should now be equivalent.", set.containsAll(integersToCheck));
+ assertTrue("The sets should now be equivalent.", integersToCheck.containsAll(set));
+ }
+
+ @Test
+ public void testRetainAll() throws Exception {
+ //Test ability to generate the intersection set
+ Set<Integer> retainSet = Sets.newHashSet();
+ fillSet(10, set);
+ assertTrue("The set should have changed.", set.retainAll(retainSet));
+ assertTrue("The set should have been emptied.", set.isEmpty());
+ fillSet(10, set);
+ fillSet(10, retainSet);
+ Set<Integer> duplicateSet = new HashSet<>(set);
+ assertFalse("The set should not have changed.", set.retainAll(retainSet));
+ assertEquals("The set should be the same as the duplicate.", duplicateSet, set);
+ retainSet.remove(9);
+ assertTrue("The set should have changed.", set.retainAll(retainSet));
+ duplicateSet.remove(9);
+ assertEquals("The set should have had the nine element removed.", duplicateSet, set);
+ }
+
+ @Test
+ public void testRemoveAll() throws Exception {
+ //Test for mass removal and change checking
+ Set<Integer> removeSet = Sets.newHashSet();
+ fillSet(10, set);
+ Set<Integer> duplicateSet = Sets.newHashSet(set);
+ assertFalse("No elements should change.", set.removeAll(removeSet));
+ assertEquals("Set should not have diverged from the duplicate.", duplicateSet, set);
+ fillSet(5, removeSet);
+ assertTrue("Elements should have been removed.", set.removeAll(removeSet));
+ assertNotEquals("Duplicate set should no longer be equivalent.", duplicateSet, set);
+ assertEquals("Five elements should have been removed from set.", 5, set.size());
+ for (Integer item : removeSet) {
+ assertFalse("No element of remove set should remain.", set.contains(item));
+ }
+ }
+
+ @Test
+ public void testClear() throws Exception {
+ //Test set emptying
+ assertTrue("The set should be initialized empty.", set.isEmpty());
+ set.clear();
+ assertTrue("Clear should have no effect on an empty set.", set.isEmpty());
+ fillSet(10, set);
+ assertFalse("The set should no longer be empty.", set.isEmpty());
+ set.clear();
+ assertTrue("The set should be empty after clear.", set.isEmpty());
+ }
+
+ /**
+ * Populated the map with integers from (0) up to (numEntries - 1).
+ *
+ * @param numEntries number of entries to add
+ */
+ private void fillSet(int numEntries, Set<Integer> set) {
+ checkNotNull(set);
+ for (int i = 0; i < numEntries; i++) {
+ set.add(i);
+ }
+ }
+}
diff --git a/framework/src/onos/core/store/pom.xml b/framework/src/onos/core/store/pom.xml
index 2b246b83..219ae5d0 100644
--- a/framework/src/onos/core/store/pom.xml
+++ b/framework/src/onos/core/store/pom.xml
@@ -33,7 +33,8 @@
<modules>
<module>dist</module>
- <module>serializers</module>
+ <module>persistence</module>
+ <module>serializers</module>
</modules>
<dependencies>
diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java
new file mode 100644
index 00000000..6b12df96
--- /dev/null
+++ b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.serializers;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.ExtensionResolver;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+import org.onosproject.net.flow.instructions.Instructions;
+
+/**
+ * Created by jono on 10/29/15.
+ */
+public class ExtensionInstructionSerializer extends
+ Serializer<Instructions.ExtensionInstructionWrapper> {
+
+ public ExtensionInstructionSerializer() {
+ super(false, true);
+ }
+
+ @Override
+ public void write(Kryo kryo, Output output, Instructions.ExtensionInstructionWrapper object) {
+ kryo.writeClassAndObject(output, object.extensionInstruction().type());
+ kryo.writeClassAndObject(output, object.deviceId());
+
+ kryo.writeClassAndObject(output, object.extensionInstruction().serialize());
+
+ }
+
+ @Override
+ public Instructions.ExtensionInstructionWrapper read(Kryo kryo, Input input,
+ Class<Instructions.ExtensionInstructionWrapper> type) {
+ ExtensionType exType = (ExtensionType) kryo.readClassAndObject(input);
+ DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
+
+ DriverService driverService = DefaultServiceDirectory.getService(DriverService.class);
+ DriverHandler handler = new DefaultDriverHandler(
+ new DefaultDriverData(driverService.getDriver(deviceId), deviceId));
+
+ ExtensionResolver resolver = handler.behaviour(ExtensionResolver.class);
+
+ ExtensionInstruction instruction = resolver.getExtensionInstruction(exType);
+
+ byte[] bytes = (byte[]) kryo.readClassAndObject(input);
+
+ instruction.deserialize(bytes);
+
+ return Instructions.extension(instruction, deviceId);
+ }
+}
diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 5b5056cb..0312bafd 100644
--- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -70,6 +70,7 @@ import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OmsPort;
import org.onosproject.net.Port;
@@ -118,6 +119,8 @@ import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -125,8 +128,10 @@ import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
+import org.onosproject.net.flow.instructions.ExtensionType;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
@@ -337,6 +342,8 @@ public final class KryoNamespaces {
IndexedLambdaCriterion.class,
OchSignalCriterion.class,
OchSignalTypeCriterion.class,
+ OduSignalIdCriterion.class,
+ OduSignalTypeCriterion.class,
Criterion.class,
Criterion.Type.class,
DefaultTrafficTreatment.class,
@@ -349,6 +356,9 @@ public final class KryoNamespaces {
L0ModificationInstruction.L0SubType.class,
L0ModificationInstruction.ModLambdaInstruction.class,
L0ModificationInstruction.ModOchSignalInstruction.class,
+ L1ModificationInstruction.class,
+ L1ModificationInstruction.L1SubType.class,
+ L1ModificationInstruction.ModOduSignalIdInstruction.class,
L2ModificationInstruction.class,
L2ModificationInstruction.L2SubType.class,
L2ModificationInstruction.ModEtherInstruction.class,
@@ -441,6 +451,8 @@ public final class KryoNamespaces {
.register(new HostLocationSerializer(), HostLocation.class)
.register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class)
.register(new AnnotationsSerializer(), DefaultAnnotations.class)
+ .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class)
+ .register(ExtensionType.class)
.register(Versioned.class)
.register(MapEvent.class)
.register(MapEvent.Type.class)
@@ -458,6 +470,7 @@ public final class KryoNamespaces {
.register(OduCltPort.SignalType.class)
.register(IndexedLambda.class)
.register(OchSignal.class)
+ .register(OduSignalId.class)
.register(OduCltPortDescription.class)
.register(OchPortDescription.class)
.register(OmsPortDescription.class)