summaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/core')
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java3
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java9
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java143
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java4
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java2
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java22
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java33
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java28
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java3
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java21
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java29
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java168
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java6
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java32
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java3
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java8
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java8
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java14
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java4
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java2
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java4
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java10
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java2
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java2
-rw-r--r--framework/src/onos/core/store/dist/pom.xml7
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java37
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java31
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java20
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java12
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java7
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java10
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java11
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java63
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java19
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java4
-rw-r--r--framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java7
-rw-r--r--framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java2
-rw-r--r--framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java4
42 files changed, 708 insertions, 167 deletions
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java
index d81b83cc..34042dad 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/AbstractDescription.java
@@ -16,6 +16,7 @@
package org.onosproject.net;
import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.Objects;
/**
* Base implementation of an annotated model description.
@@ -46,4 +47,18 @@ public abstract class AbstractDescription implements Annotated {
return annotations;
}
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(annotations);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof AbstractDescription) {
+ AbstractDescription that = (AbstractDescription) object;
+ return Objects.equal(this.annotations, that.annotations);
+ }
+ return false;
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java
index 2877701e..557fa5c1 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultHost.java
@@ -98,7 +98,8 @@ public class DefaultHost extends AbstractElement implements Host {
return Objects.equals(this.id, other.id) &&
Objects.equals(this.mac, other.mac) &&
Objects.equals(this.vlan, other.vlan) &&
- Objects.equals(this.location, other.location);
+ Objects.equals(this.location, other.location) &&
+ Objects.equals(this.ipAddresses(), other.ipAddresses());
}
return false;
}
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 e3d6993c..cf7bed6d 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,15 @@ public interface BridgeConfig extends HandlerBehaviour {
void addBridge(BridgeName bridgeName);
/**
+ * Adds a bridge with given bridge name, dpid and exPortName.
+ *
+ * @param bridgeName bridge name
+ * @param dpid dpid
+ * @param exPortName external port name
+ */
+ void addBridge(BridgeName bridgeName, String dpid, String exPortName);
+
+ /**
* Adds a bridge with given bridge name and dpid, and sets the controller
* of the bridge with given controllers.
*
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java
index 5cdc0c12..3757d327 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/Config.java
@@ -20,10 +20,15 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import java.util.function.Function;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -51,6 +56,21 @@ public abstract class Config<S> {
protected ConfigApplyDelegate delegate;
/**
+ * Indicator of whether a configuration JSON field is required.
+ */
+ public enum FieldPresence {
+ /**
+ * Signifies that config field is an optional one.
+ */
+ OPTIONAL,
+
+ /**
+ * Signifies that config field is mandatory.
+ */
+ MANDATORY
+ }
+
+ /**
* Initializes the configuration behaviour with necessary context.
*
* @param subject configuration subject
@@ -71,6 +91,29 @@ public abstract class Config<S> {
}
/**
+ * Indicates whether or not the backing JSON node contains valid data.
+ * <p>
+ * Default implementation returns true.
+ * Subclasses are expected to override this with their own validation.
+ * </p>
+ *
+ * @return true if the data is valid; false otherwise
+ */
+ public boolean isValid() {
+ // TODO: figure out what assertions could be made in the base class
+ // NOTE: The thought is to have none, but instead to provide a set
+ // of predicates to allow configs to test validity of present fields,
+ // e.g.:
+ // isString(path)
+ // isBoolean(path)
+ // isNumber(path, [min, max])
+ // isDecimal(path, [min, max])
+ // isMacAddress(path)
+ // isIpAddress(path)
+ return true;
+ }
+
+ /**
* Returns the specific subject to which this configuration pertains.
*
* @return configuration subject
@@ -309,4 +352,104 @@ public abstract class Config<S> {
return this;
}
+ /**
+ * Indicates whether only the specified fields are present in the backing JSON.
+ *
+ * @param allowedFields allowed field names
+ * @return true if all allowedFields are present; false otherwise
+ */
+ protected boolean hasOnlyFields(String... allowedFields) {
+ Set<String> fields = ImmutableSet.copyOf(allowedFields);
+ return !Iterators.any(object.fieldNames(), f -> !fields.contains(f));
+ }
+
+ /**
+ * Indicates whether the specified field holds a valid MAC address.
+ *
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @return true if valid; false otherwise
+ * @throws IllegalArgumentException if field is present, but not valid MAC
+ */
+ protected boolean isMacAddress(String field, FieldPresence presence) {
+ JsonNode node = object.path(field);
+ return isValid(node, presence, node.isTextual() &&
+ MacAddress.valueOf(node.asText()) != null);
+ }
+
+ /**
+ * Indicates whether the specified field holds a valid IP address.
+ *
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @return true if valid; false otherwise
+ * @throws IllegalArgumentException if field is present, but not valid IP
+ */
+ protected boolean isIpAddress(String field, FieldPresence presence) {
+ JsonNode node = object.path(field);
+ return isValid(node, presence, node.isTextual() &&
+ IpAddress.valueOf(node.asText()) != null);
+ }
+
+ /**
+ * Indicates whether the specified field holds a valid string value.
+ *
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param pattern optional regex pattern
+ * @return true if valid; false otherwise
+ * @throws IllegalArgumentException if field is present, but not valid MAC
+ */
+ protected boolean isString(String field, FieldPresence presence, String... pattern) {
+ JsonNode node = object.path(field);
+ return isValid(node, presence, node.isTextual() &&
+ (pattern.length > 0 && node.asText().matches(pattern[0]) || pattern.length < 1));
+ }
+
+ /**
+ * Indicates whether the specified field holds a valid number.
+ *
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param minMax optional min/max values
+ * @return true if valid; false otherwise
+ * @throws IllegalArgumentException if field is present, but not valid
+ */
+ protected boolean isNumber(String field, FieldPresence presence, long... minMax) {
+ JsonNode node = object.path(field);
+ return isValid(node, presence, (node.isLong() || node.isInt()) &&
+ (minMax.length > 0 && minMax[0] <= node.asLong() || minMax.length < 1) &&
+ (minMax.length > 1 && minMax[1] > node.asLong() || minMax.length < 2));
+ }
+
+ /**
+ * Indicates whether the specified field holds a valid decimal number.
+ *
+ * @param field JSON field name
+ * @param presence specifies if field is optional or mandatory
+ * @param minMax optional min/max values
+ * @return true if valid; false otherwise
+ * @throws IllegalArgumentException if field is present, but not valid
+ */
+ protected boolean isDecimal(String field, FieldPresence presence, double... minMax) {
+ JsonNode node = object.path(field);
+ return isValid(node, presence, (node.isDouble() || node.isFloat()) &&
+ (minMax.length > 0 && minMax[0] <= node.asDouble() || minMax.length < 1) &&
+ (minMax.length > 1 && minMax[1] > node.asDouble() || minMax.length < 2));
+ }
+
+ /**
+ * Indicates whether the node is present and of correct value or not
+ * mandatory and absent.
+ *
+ * @param node JSON node
+ * @param presence specifies if field is optional or mandatory
+ * @param correctValue true if the value is correct
+ * @return true if the field is as expected
+ */
+ private boolean isValid(JsonNode node, FieldPresence presence, boolean correctValue) {
+ boolean isMandatory = presence == FieldPresence.MANDATORY;
+ return isMandatory && correctValue || !isMandatory && !node.isNull() || correctValue;
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java
index 8eb69a45..f1b22c41 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigService.java
@@ -119,7 +119,7 @@ public interface NetworkConfigService
/**
* Applies configuration for the specified subject and configuration
- * class using the raw JSON object. If configuration already exists, it
+ * class using the raw JSON node. If configuration already exists, it
* will be updated.
*
* @param subject configuration subject
@@ -128,6 +128,8 @@ public interface NetworkConfigService
* @param <S> type of subject
* @param <C> type of configuration
* @return configuration or null if one is not available
+ * @throws IllegalArgumentException if the supplied JSON node contains
+ * invalid data
*/
<S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
JsonNode json);
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java
index 9dd66e8d..9be4b120 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/config/NetworkConfigStore.java
@@ -113,6 +113,8 @@ public interface NetworkConfigStore extends Store<NetworkConfigEvent, NetworkCon
* @param <S> type of subject
* @param <C> type of configuration
* @return configuration object
+ * @throws IllegalArgumentException if the supplied JSON node contains
+ * invalid data
*/
<S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
JsonNode json);
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
index 0fcc800d..9074792c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultDeviceDescription.java
@@ -24,6 +24,7 @@ import java.net.URI;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.Device.Type;
+import com.google.common.base.Objects;
/**
* Default implementation of immutable device description entity.
@@ -132,6 +133,30 @@ public class DefaultDeviceDescription extends AbstractDescription
.toString();
}
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), uri, type, manufacturer,
+ hwVersion, swVersion, serialNumber, chassisId);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof DefaultDeviceDescription) {
+ if (!super.equals(object)) {
+ return false;
+ }
+ DefaultDeviceDescription that = (DefaultDeviceDescription) object;
+ return Objects.equal(this.uri, that.uri)
+ && Objects.equal(this.type, that.type)
+ && Objects.equal(this.manufacturer, that.manufacturer)
+ && Objects.equal(this.hwVersion, that.hwVersion)
+ && Objects.equal(this.swVersion, that.swVersion)
+ && Objects.equal(this.serialNumber, that.serialNumber)
+ && Objects.equal(this.chassisId, that.chassisId);
+ }
+ return false;
+ }
+
// default constructor for serialization
private DefaultDeviceDescription() {
this.uri = null;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java
index 572d201c..d62e932c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DefaultPortDescription.java
@@ -21,6 +21,7 @@ import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import static org.onosproject.net.Port.Type;
+import com.google.common.base.Objects;
/**
* Default implementation of immutable port description.
@@ -117,4 +118,25 @@ public class DefaultPortDescription extends AbstractDescription
.toString();
}
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), number, isEnabled, type,
+ portSpeed);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object != null && getClass() == object.getClass()) {
+ if (!super.equals(object)) {
+ return false;
+ }
+ DefaultPortDescription that = (DefaultPortDescription) object;
+ return Objects.equal(this.number, that.number)
+ && Objects.equal(this.isEnabled, that.isEnabled)
+ && Objects.equal(this.type, that.type)
+ && Objects.equal(this.portSpeed, that.portSpeed);
+ }
+ return false;
+ }
+
}
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 453a7648..a842d600 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
@@ -23,6 +23,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -353,6 +354,26 @@ public final class DefaultTrafficSelector implements TrafficSelector {
}
@Override
+ public Builder matchArpTpa(Ip4Address addr) {
+ return add(Criteria.matchArpTpa(addr));
+ }
+
+ @Override
+ public Builder matchArpSpa(Ip4Address addr) {
+ return add(Criteria.matchArpSpa(addr));
+ }
+
+ @Override
+ public Builder matchArpTha(MacAddress addr) {
+ return add(Criteria.matchArpTha(addr));
+ }
+
+ @Override
+ public Builder matchArpSha(MacAddress addr) {
+ return add(Criteria.matchArpSha(addr));
+ }
+
+ @Override
public TrafficSelector build() {
return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values()));
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
index 1286ffc1..9fe88d5a 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
@@ -17,6 +17,7 @@ package org.onosproject.net.flow;
import java.util.Set;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -386,6 +387,38 @@ public interface TrafficSelector {
Builder matchIPv6ExthdrFlags(short exthdrFlags);
/**
+ * Matches a arp IPv4 destination address.
+ *
+ * @param addr a arp IPv4 destination address
+ * @return a selection builder
+ */
+ Builder matchArpTpa(Ip4Address addr);
+
+ /**
+ * Matches a arp IPv4 source address.
+ *
+ * @param addr a arp IPv4 source address
+ * @return a selection builder
+ */
+ Builder matchArpSpa(Ip4Address addr);
+
+ /**
+ * Matches a arp_eth_dst address.
+ *
+ * @param addr a arp_eth_dst address
+ * @return a selection builder
+ */
+ Builder matchArpTha(MacAddress addr);
+
+ /**
+ * Matches a arp_eth_src address.
+ *
+ * @param addr a arp_eth_src address
+ * @return a selection builder
+ */
+ Builder matchArpSha(MacAddress addr);
+
+ /**
* Builds an immutable traffic selector.
*
* @return traffic selector
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
index bc1a094c..554b8e74 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
@@ -510,9 +510,9 @@ public final class Criteria {
}
/**
- * Creates a match on IPv4 source field using the specified value.
+ * Creates a match on IPv4 destination field using the specified value.
*
- * @param ip ipv4 source value
+ * @param ip ipv4 destination value
* @return match criterion
*/
public static Criterion matchArpTpa(Ip4Address ip) {
@@ -520,15 +520,35 @@ public final class Criteria {
}
/**
- * Creates a match on MAC source field using the specified value.
+ * Creates a match on IPv4 source field using the specified value.
*
- * @param mac MAC source value
+ * @param ip ipv4 source value
+ * @return match criterion
+ */
+ public static Criterion matchArpSpa(Ip4Address ip) {
+ return new ArpPaCriterion(ip, Type.ARP_SPA);
+ }
+
+ /**
+ * Creates a match on MAC destination field using the specified value.
+ *
+ * @param mac MAC destination value
* @return match criterion
*/
public static Criterion matchArpTha(MacAddress mac) {
return new ArpHaCriterion(mac, Type.ARP_THA);
}
+ /**
+ * Creates a match on MAC source field using the specified value.
+ *
+ * @param mac MAC source value
+ * @return match criterion
+ */
+ public static Criterion matchArpSha(MacAddress mac) {
+ return new ArpHaCriterion(mac, Type.ARP_SHA);
+ }
+
public static Criterion dummy() {
return new DummyCriterion();
}
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
index 747a85b5..3e1cb75c 100644
--- 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
@@ -32,7 +32,8 @@ public final class ExtensionType {
*/
public enum ExtensionTypes {
// TODO fix type numbers to include experimenter id
- NICIRA_SET_TUNNEL_DST(31);
+ NICIRA_SET_TUNNEL_DST(31),
+ NICIRA_RESUBMIT(32);
private ExtensionType type;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
index 1f05197a..307a6078 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
@@ -28,6 +28,7 @@ import org.onlab.packet.VlanId;
import com.google.common.collect.ImmutableSet;
import static com.google.common.base.MoreObjects.toStringHelper;
+import com.google.common.base.Objects;
/**
* Default implementation of an immutable host description.
@@ -119,4 +120,24 @@ public class DefaultHostDescription extends AbstractDescription
.toString();
}
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), mac, vlan, location, ip);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object != null && getClass() == object.getClass()) {
+ if (!super.equals(object)) {
+ return false;
+ }
+ DefaultHostDescription that = (DefaultHostDescription) object;
+ return Objects.equal(this.mac, that.mac)
+ && Objects.equal(this.vlan, that.vlan)
+ && Objects.equal(this.location, that.location)
+ && Objects.equal(this.ip, that.ip);
+ }
+ return false;
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
index 58ac0bb8..92824cf8 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
@@ -18,7 +18,6 @@ package org.onosproject.net.host;
import org.joda.time.LocalDateTime;
import org.onosproject.event.AbstractEvent;
import org.onosproject.net.Host;
-import org.onosproject.net.HostLocation;
import static com.google.common.base.MoreObjects.toStringHelper;
@@ -52,7 +51,7 @@ public class HostEvent extends AbstractEvent<HostEvent.Type, Host> {
HOST_MOVED
}
- private HostLocation prevLocation;
+ private Host prevSubject;
/**
* Creates an event of a given type and for the specified host and the
@@ -77,25 +76,29 @@ public class HostEvent extends AbstractEvent<HostEvent.Type, Host> {
}
/**
- * Creates an event with HOST_MOVED type along with the previous location
- * of the host.
+ * Creates an event with previous subject.
*
+ * The previous subject is ignored if the type is not moved or updated
+ *
+ * @param type host event type
* @param host event host subject
- * @param prevLocation previous location of the host
+ * @param prevSubject previous host subject
*/
- public HostEvent(Host host, HostLocation prevLocation) {
- super(Type.HOST_MOVED, host);
- this.prevLocation = prevLocation;
+ public HostEvent(Type type, Host host, Host prevSubject) {
+ super(type, host);
+ if (type == Type.HOST_MOVED || type == Type.HOST_UPDATED) {
+ this.prevSubject = prevSubject;
+ }
}
/**
- * Gets the previous location information in this host event.
+ * Gets the previous subject in this host event.
*
- * @return the previous location, or null if previous location is not
+ * @return the previous subject, or null if previous subject is not
* specified.
*/
- public HostLocation prevLocation() {
- return this.prevLocation;
+ public Host prevSubject() {
+ return this.prevSubject;
}
@Override
@@ -104,7 +107,7 @@ public class HostEvent extends AbstractEvent<HostEvent.Type, Host> {
.add("time", new LocalDateTime(time()))
.add("type", type())
.add("subject", subject())
- .add("prevLocation", prevLocation())
+ .add("prevSubject", prevSubject())
.toString();
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java
index 891eb65d..cba17640 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/link/DefaultLinkDescription.java
@@ -20,6 +20,7 @@ import org.onosproject.net.AbstractDescription;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.SparseAnnotations;
+import com.google.common.base.Objects;
/**
* Default implementation of immutable link description entity.
@@ -70,4 +71,23 @@ public class DefaultLinkDescription extends AbstractDescription
.add("type", type()).toString();
}
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), src, dst, type);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object != null && getClass() == object.getClass()) {
+ if (!super.equals(object)) {
+ return false;
+ }
+ DefaultLinkDescription that = (DefaultLinkDescription) object;
+ return Objects.equal(this.src, that.src)
+ && Objects.equal(this.dst, that.dst)
+ && Objects.equal(this.type, that.type);
+ }
+ return false;
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java
index 3aa29f6b..d87682a9 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourcePath.java
@@ -19,12 +19,14 @@ import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
-import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
/**
* An object that is used to locate a resource in a network.
@@ -32,32 +34,45 @@ import static com.google.common.base.Preconditions.checkNotNull;
* of elementary resources that are not globally identifiable. A ResourcePath can be a globally
* unique resource identifier.
*
+ * Two types of resource are considered. One is discrete type and the other is continuous type.
+ * Discrete type resource is a resource whose amount is measured as a discrete unit. VLAN ID and
+ * MPLS label are examples of discrete type resource. Continuous type resource is a resource whose
+ * amount is measured as a continuous value. Bandwidth is an example of continuous type resource.
+ * A double value is associated with a continuous type value.
+ *
* Users of this class must keep the semantics of resources regarding the hierarchical structure.
* For example, resource path, Link:1/VLAN ID:100, is valid, but resource path, VLAN ID:100/Link:1
* is not valid because a link is not a sub-component of a VLAN ID.
*/
@Beta
-public final class ResourcePath {
+public abstract class ResourcePath {
- private final List<Object> resources;
+ private final Discrete parent;
+ private final Object last;
- public static final ResourcePath ROOT = new ResourcePath(ImmutableList.of());
+ public static final Discrete ROOT = new Discrete();
- public static ResourcePath child(ResourcePath parent, Object child) {
- ImmutableList<Object> components = ImmutableList.builder()
- .addAll(parent.components())
- .add(child)
- .build();
- return new ResourcePath(components);
+ /**
+ * Creates an resource path which represents a discrete-type resource from the specified components.
+ *
+ * @param components components of the path. The order represents hierarchical structure of the resource.
+ */
+ public static ResourcePath discrete(Object... components) {
+ if (components.length == 0) {
+ return ROOT;
+ } else {
+ return new Discrete(ImmutableList.copyOf(components));
+ }
}
/**
- * Creates an resource path from the specified components.
+ * Creates an resource path which represents a continuous-type resource from the specified components.
*
+ * @param value amount of the resource
* @param components components of the path. The order represents hierarchical structure of the resource.
*/
- public ResourcePath(Object... components) {
- this(Arrays.asList(components));
+ public static ResourcePath continuous(double value, Object... components) {
+ return new Continuous(ImmutableList.copyOf(components), value);
}
/**
@@ -65,15 +80,37 @@ public final class ResourcePath {
*
* @param components components of the path. The order represents hierarchical structure of the resource.
*/
- public ResourcePath(List<Object> components) {
+ ResourcePath(List<Object> components) {
checkNotNull(components);
+ checkArgument(!components.isEmpty());
+
+ LinkedList<Object> children = new LinkedList<>(components);
+ this.last = children.pollLast();
+ if (children.isEmpty()) {
+ this.parent = ROOT;
+ } else {
+ this.parent = new Discrete(children);
+ }
+ }
- this.resources = ImmutableList.copyOf(components);
+ /**
+ * Creates an resource path from the specified parent and child.
+ *
+ * @param parent the parent of this resource
+ * @param last a child of the parent
+ */
+ ResourcePath(Discrete parent, Object last) {
+ checkNotNull(parent);
+ checkNotNull(last);
+
+ this.parent = parent;
+ this.last = last;
}
// for serialization
private ResourcePath() {
- this.resources = null;
+ this.parent = null;
+ this.last = null;
}
/**
@@ -82,7 +119,15 @@ public final class ResourcePath {
* @return the components of this resource path
*/
public List<Object> components() {
- return resources;
+ LinkedList<Object> components = new LinkedList<>();
+
+ ResourcePath current = this;
+ while (current.parent().isPresent()) {
+ components.addFirst(current.last);
+ current = current.parent;
+ }
+
+ return components;
}
/**
@@ -92,21 +137,20 @@ public final class ResourcePath {
* @return the parent resource path of this instance.
* If there is no parent, empty instance will be returned.
*/
- public Optional<ResourcePath> parent() {
- if (!isRoot()) {
- return Optional.of(new ResourcePath(resources.subList(0, resources.size() - 1)));
- }
+ public Optional<Discrete> parent() {
+ return Optional.ofNullable(parent);
+ }
+
+ public ResourcePath child(Object child) {
+ checkState(this instanceof Discrete);
- return Optional.empty();
+ return new Discrete((Discrete) this, child);
}
- /**
- * Returns true if the path represents root.
- *
- * @return true if the path represents root, false otherwise.
- */
- public boolean isRoot() {
- return resources.size() == 0;
+ public ResourcePath child(Object child, double value) {
+ checkState(this instanceof Discrete);
+
+ return new Continuous((Discrete) this, child, value);
}
/**
@@ -115,14 +159,13 @@ public final class ResourcePath {
* @return the last component of this instance.
* The return value is equal to the last object of {@code components()}.
*/
- public Object lastComponent() {
- int last = resources.size() - 1;
- return resources.get(last);
+ public Object last() {
+ return last;
}
@Override
public int hashCode() {
- return resources.hashCode();
+ return Objects.hash(this.parent, this.last);
}
@Override
@@ -134,13 +177,68 @@ public final class ResourcePath {
return false;
}
final ResourcePath that = (ResourcePath) obj;
- return Objects.equals(this.resources, that.resources);
+ return Objects.equals(this.parent, that.parent)
+ && Objects.equals(this.last, that.last);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
- .add("resources", resources)
+ .add("parent", parent)
+ .add("last", last)
.toString();
}
+
+ /**
+ * Represents a resource path which specifies a resource which can be measured
+ * as a discrete unit. A VLAN ID and a MPLS label of a link are examples of the resource.
+ * <p>
+ * Note: This class is exposed to the public, but intended to be used in the resource API
+ * implementation only. It is not for resource API user.
+ * </p>
+ */
+ public static final class Discrete extends ResourcePath {
+ private Discrete() {
+ super();
+ }
+
+ private Discrete(List<Object> components) {
+ super(components);
+ }
+
+ private Discrete(Discrete parent, Object last) {
+ super(parent, last);
+ }
+ }
+
+ /**
+ * Represents a resource path which specifies a resource which can be measured
+ * as continuous value. Bandwidth of a link is an example of the resource.
+ * <p>
+ * Note: This class is exposed to the public, but intended to be used in the resource API
+ * implementation only. It is not for resource API user.
+ */
+ public static final class Continuous extends ResourcePath {
+ // Note: value is not taken into account for equality
+ private final double value;
+
+ private Continuous(List<Object> components, double value) {
+ super(components);
+ this.value = value;
+ }
+
+ public Continuous(Discrete parent, Object last, double value) {
+ super(parent, last);
+ this.value = value;
+ }
+
+ /**
+ * Returns the value of the resource amount.
+ *
+ * @return the value of the resource amount
+ */
+ public double value() {
+ return value;
+ }
+ }
}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java
index a84927a0..5f448221 100644
--- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourceAllocationTest.java
@@ -38,9 +38,9 @@ public class ResourceAllocationTest {
@Test
public void testEquals() {
- ResourceAllocation alloc1 = new ResourceAllocation(new ResourcePath(LK1, VLAN1), IID1);
- ResourceAllocation sameAsAlloc1 = new ResourceAllocation(new ResourcePath(LK1, VLAN1), IID1);
- ResourceAllocation alloc2 = new ResourceAllocation(new ResourcePath(LK2, VLAN1), IID1);
+ ResourceAllocation alloc1 = new ResourceAllocation(ResourcePath.discrete(LK1, VLAN1), IID1);
+ ResourceAllocation sameAsAlloc1 = new ResourceAllocation(ResourcePath.discrete(LK1, VLAN1), IID1);
+ ResourceAllocation alloc2 = new ResourceAllocation(ResourcePath.discrete(LK2, VLAN1), IID1);
new EqualsTester()
.addEqualityGroup(alloc1, sameAsAlloc1)
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java
index 4a8886a4..35dcf1ec 100644
--- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/newresource/ResourcePathTest.java
@@ -18,6 +18,7 @@ package org.onosproject.net.newresource;
import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.LinkKey;
@@ -25,6 +26,7 @@ import org.onosproject.net.PortNumber;
import java.util.Optional;
+import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@@ -36,37 +38,49 @@ public class ResourcePathTest {
private static final ConnectPoint CP1_1 = new ConnectPoint(D1, P1);
private static final ConnectPoint CP2_1 = new ConnectPoint(D2, P1);
private static final VlanId VLAN1 = VlanId.vlanId((short) 100);
+ private static final Bandwidth BW1 = Bandwidth.gbps(2);
+ private static final Bandwidth BW2 = Bandwidth.gbps(1);
@Test
public void testEquals() {
- ResourcePath resource1 = new ResourcePath(LinkKey.linkKey(CP1_1, CP2_1), VLAN1);
- ResourcePath sameAsResource1 = new ResourcePath(LinkKey.linkKey(CP1_1, CP2_1), VLAN1);
- ResourcePath resource2 = new ResourcePath(LinkKey.linkKey(CP2_1, CP1_1), VLAN1);
+ ResourcePath resource1 = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1), VLAN1);
+ ResourcePath sameAsResource1 = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1), VLAN1);
+ ResourcePath resource2 = ResourcePath.discrete(LinkKey.linkKey(CP2_1, CP1_1), VLAN1);
+ ResourcePath resource3 = ResourcePath.continuous(BW1.bps(), LinkKey.linkKey(CP1_1, CP2_1), BW1);
+ ResourcePath sameAsResource3 = ResourcePath.continuous(BW2.bps(), LinkKey.linkKey(CP1_1, CP2_1), BW1);
new EqualsTester()
.addEqualityGroup(resource1, sameAsResource1)
.addEqualityGroup(resource2)
+ .addEqualityGroup(resource3, sameAsResource3) // this is intentional
.testEquals();
}
@Test
public void testCreateWithZeroComponent() {
- ResourcePath path = new ResourcePath();
+ ResourcePath path = ResourcePath.discrete();
assertThat(path, is(ResourcePath.ROOT));
}
@Test
+ public void testComponents() {
+ ResourcePath port = ResourcePath.discrete(D1, P1);
+
+ assertThat(port.components(), contains(D1, P1));
+ }
+
+ @Test
public void testThereIsParent() {
- ResourcePath path = new ResourcePath(LinkKey.linkKey(CP1_1, CP2_1), VLAN1);
- ResourcePath parent = new ResourcePath(LinkKey.linkKey(CP1_1, CP2_1));
+ ResourcePath path = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1), VLAN1);
+ ResourcePath parent = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1));
assertThat(path.parent(), is(Optional.of(parent)));
}
@Test
public void testNoParent() {
- ResourcePath path = new ResourcePath(LinkKey.linkKey(CP1_1, CP2_1));
+ ResourcePath path = ResourcePath.discrete(LinkKey.linkKey(CP1_1, CP2_1));
assertThat(path.parent(), is(Optional.of(ResourcePath.ROOT)));
}
@@ -74,9 +88,9 @@ public class ResourcePathTest {
@Test
public void testBase() {
LinkKey linkKey = LinkKey.linkKey(CP1_1, CP2_1);
- ResourcePath path = new ResourcePath(linkKey);
+ ResourcePath path = ResourcePath.discrete(linkKey);
- LinkKey child = (LinkKey) path.lastComponent();
+ LinkKey child = (LinkKey) path.last();
assertThat(child, is(linkKey));
}
}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java b/framework/src/onos/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
index 4f612de2..02462e85 100644
--- a/framework/src/onos/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
@@ -30,7 +30,8 @@ import org.onlab.util.KryoNamespace;
import org.onosproject.cluster.NodeId;
import org.onosproject.store.Timestamp;
-import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.*;
+import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
+import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
/**
* Testing version of an Eventually Consistent Map.
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 acc5a5d5..718c7bbf 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
@@ -121,7 +121,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
List<ResourcePath> resources = labels.entrySet().stream()
- .map(x -> new ResourcePath(linkKey(x.getKey().src(), x.getKey().src()), x.getValue()))
+ .map(x -> ResourcePath.discrete(linkKey(x.getKey().src(), x.getKey().src()), x.getValue()))
.collect(Collectors.toList());
List<org.onosproject.net.newresource.ResourceAllocation> allocations =
resourceService.allocate(intent.id(), resources);
@@ -145,9 +145,9 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private Optional<MplsLabel> findMplsLabel(LinkKey link) {
- return resourceService.getAvailableResources(new ResourcePath(link)).stream()
- .filter(x -> x.lastComponent() instanceof MplsLabel)
- .map(x -> (MplsLabel) x.lastComponent())
+ return resourceService.getAvailableResources(ResourcePath.discrete(link)).stream()
+ .filter(x -> x.last() instanceof MplsLabel)
+ .map(x -> (MplsLabel) x.last())
.findFirst();
}
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 fce8498c..ee04aab5 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
@@ -160,8 +160,8 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
log.debug("Compiling optical circuit intent between {} and {}", src, dst);
// Reserve OduClt ports
- ResourcePath srcPortPath = new ResourcePath(src.deviceId(), src.port());
- ResourcePath dstPortPath = new ResourcePath(dst.deviceId(), dst.port());
+ ResourcePath srcPortPath = ResourcePath.discrete(src.deviceId(), src.port());
+ ResourcePath dstPortPath = ResourcePath.discrete(dst.deviceId(), dst.port());
List<ResourceAllocation> allocation = resourceService.allocate(intent.id(), srcPortPath, dstPortPath);
if (allocation.isEmpty()) {
throw new IntentCompilationException("Unable to reserve ports for intent " + intent);
@@ -312,7 +312,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
if (ochCP != null) {
OchPort ochPort = (OchPort) deviceService.getPort(ochCP.deviceId(), ochCP.port());
Optional<IntentId> intentId =
- resourceService.getResourceAllocation(new ResourcePath(ochCP.deviceId(), ochCP.port()))
+ resourceService.getResourceAllocation(ResourcePath.discrete(ochCP.deviceId(), ochCP.port()))
.map(ResourceAllocation::consumer)
.filter(x -> x instanceof IntentId)
.map(x -> (IntentId) x);
@@ -331,7 +331,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu
}
Optional<IntentId> intentId =
- resourceService.getResourceAllocation(new ResourcePath(oduPort.deviceId(), port.number()))
+ resourceService.getResourceAllocation(ResourcePath.discrete(oduPort.deviceId(), port.number()))
.map(ResourceAllocation::consumer)
.filter(x -> x instanceof IntentId)
.map(x -> (IntentId) x);
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 d6725b7c..a4ed551a 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
@@ -107,8 +107,8 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
log.debug("Compiling optical connectivity intent between {} and {}", src, dst);
// Reserve OCh ports
- ResourcePath srcPortPath = new ResourcePath(src.deviceId(), src.port());
- ResourcePath dstPortPath = new ResourcePath(dst.deviceId(), dst.port());
+ ResourcePath srcPortPath = ResourcePath.discrete(src.deviceId(), src.port());
+ ResourcePath dstPortPath = ResourcePath.discrete(dst.deviceId(), dst.port());
List<org.onosproject.net.newresource.ResourceAllocation> allocation =
resourceService.allocate(intent.id(), srcPortPath, dstPortPath);
if (allocation.isEmpty()) {
@@ -182,8 +182,8 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
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))
+ .map(x -> ResourcePath.discrete(linkKey(x.src(), x.dst())))
+ .map(x -> x.child(minLambda))
.collect(Collectors.toList());
List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources);
@@ -196,10 +196,10 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) {
return links.stream()
- .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(x -> ResourcePath.discrete(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 -> Iterables.filter(x, r -> r.last() instanceof IndexedLambda))
+ .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.last()))
.map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x))
.reduce(Sets::intersection)
.orElse(Collections.emptySet());
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
index e6d92253..066dd33e 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceDeviceListener.java
@@ -75,12 +75,12 @@ final class ResourceDeviceListener implements DeviceListener {
}
private void registerPortResource(Device device, Port port) {
- ResourcePath parent = new ResourcePath(device.id());
+ ResourcePath parent = ResourcePath.discrete(device.id());
executor.submit(() -> adminService.registerResources(parent, port.number()));
}
private void unregisterPortResource(Device device, Port port) {
- ResourcePath parent = new ResourcePath(device.id());
+ ResourcePath parent = ResourcePath.discrete(device.id());
executor.submit(() -> adminService.unregisterResources(parent, port.number()));
}
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java
index f04c78b9..68fd6612 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java
@@ -87,7 +87,7 @@ final class ResourceLinkListener implements LinkListener {
LinkKey linkKey = LinkKey.linkKey(link);
adminService.registerResources(ResourcePath.ROOT, linkKey);
- ResourcePath linkPath = new ResourcePath(linkKey);
+ ResourcePath linkPath = ResourcePath.discrete(linkKey);
// register VLAN IDs against the link
if (isEnabled(link, this::isVlanEnabled)) {
adminService.registerResources(linkPath, ENTIRE_VLAN_IDS);
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 77a32f45..1c6930bb 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
@@ -169,7 +169,7 @@ public final class ResourceManager extends AbstractListenerManager<ResourceEvent
checkNotNull(children);
checkArgument(!children.isEmpty());
- List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x));
+ List<ResourcePath> resources = Lists.transform(children, parent::child);
return store.register(resources);
}
@@ -179,7 +179,7 @@ public final class ResourceManager extends AbstractListenerManager<ResourceEvent
checkNotNull(children);
checkArgument(!children.isEmpty());
- List<ResourcePath> resources = Lists.transform(children, x -> ResourcePath.child(parent, x));
+ List<ResourcePath> resources = Lists.transform(children, parent::child);
return store.unregister(resources);
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
index 8e87a07d..793030f2 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
@@ -312,9 +312,13 @@ public class PacketManager
public void processPacket(PacketContext context) {
// TODO filter packets sent to processors based on registrations
for (ProcessorEntry entry : processors) {
- long start = System.nanoTime();
- entry.processor().process(context);
- entry.addNanos(System.nanoTime() - start);
+ try {
+ long start = System.nanoTime();
+ entry.processor().process(context);
+ entry.addNanos(System.nanoTime() - start);
+ } catch (Exception e) {
+ log.warn("Packet processor {} threw an exception", entry.processor(), e);
+ }
}
}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java
index 8d7452b3..eb7f2ccd 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java
@@ -231,7 +231,7 @@ public class ObjectiveTrackerTest {
@Test
public void testResourceEvent() throws Exception {
ResourceEvent event = new ResourceEvent(RESOURCE_ADDED,
- new ResourcePath(linkKey(link("a", 1, "b", 1))));
+ ResourcePath.discrete(linkKey(link("a", 1, "b", 1))));
resourceListener.event(event);
assertThat(
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
index 8ec09bd1..f5d3d0f3 100644
--- 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
@@ -90,7 +90,7 @@ class MockResourceService implements ResourceService {
@Override
public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
- ResourcePath resource = ResourcePath.child(parent, MplsLabel.mplsLabel(10));
+ ResourcePath resource = parent.child(MplsLabel.mplsLabel(10));
return ImmutableList.of(resource);
}
diff --git a/framework/src/onos/core/store/dist/pom.xml b/framework/src/onos/core/store/dist/pom.xml
index f2ec2a71..0b8b72bc 100644
--- a/framework/src/onos/core/store/dist/pom.xml
+++ b/framework/src/onos/core/store/dist/pom.xml
@@ -69,6 +69,12 @@
</dependency>
<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-persistence</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
<version>1.0.8</version>
@@ -110,5 +116,4 @@
<artifactId>onlab-thirdparty</artifactId>
</dependency>
</dependencies>
-
</project>
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java
index dda820ae..fe4aa0be 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/app/GossipApplicationStore.java
@@ -183,21 +183,34 @@ public class GossipApplicationStore extends ApplicationArchive
* they are marked to be active.
*/
private void loadFromDisk() {
- for (String name : getApplicationNames()) {
- for (int i = 0; i < MAX_LOAD_RETRIES; i++) {
- try {
- Application app = create(getApplicationDescription(name), false);
- if (app != null && isActive(app.id().name())) {
- requiredBy.put(app.id(), coreAppId);
- activate(app.id(), false);
- // load app permissions
- }
- } catch (Exception e) {
- log.warn("Unable to load application {} from disk; retrying", name);
- randomDelay(RETRY_DELAY_MS); // FIXME: This is a deliberate hack; fix in Drake
+ getApplicationNames().forEach(appName -> {
+ Application app = loadFromDisk(appName);
+ if (app != null && isActive(app.id().name())) {
+ activate(app.id(), false);
+ // TODO Load app permissions
+ }
+ });
+ }
+
+ private Application loadFromDisk(String appName) {
+ for (int i = 0; i < MAX_LOAD_RETRIES; i++) {
+ try {
+ // Directly return if app already exists
+ ApplicationId appId = getId(appName);
+ if (appId != null) {
+ return getApplication(appId);
}
+
+ ApplicationDescription appDesc = getApplicationDescription(appName);
+ boolean success = appDesc.requiredApps().stream()
+ .noneMatch(requiredApp -> loadFromDisk(requiredApp) == null);
+ return success ? create(appDesc, false) : null;
+ } catch (Exception e) {
+ log.warn("Unable to load application {} from disk; retrying", appName);
+ randomDelay(RETRY_DELAY_MS); //FIXME: This is a deliberate hack; fix in Falcon
}
}
+ return null;
}
@Deactivate
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
index e4a09cef..3cd992bb 100644
--- 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
@@ -7,6 +7,7 @@ import static org.slf4j.LoggerFactory.getLogger;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
+import java.net.Inet4Address;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Collection;
@@ -58,6 +59,7 @@ public class StaticClusterMetadataStore
private static final String ONOS_IP = "ONOS_IP";
private static final String ONOS_INTERFACE = "ONOS_INTERFACE";
+ private static final String ONOS_ALLOW_IPV6 = "ONOS_ALLOW_IPV6";
private static final String DEFAULT_ONOS_INTERFACE = "eth0";
private static final String CLUSTER_METADATA_FILE = "../config/cluster.json";
private static final int DEFAULT_ONOS_PORT = 9876;
@@ -214,13 +216,25 @@ public class StaticClusterMetadataStore
useOnosInterface = DEFAULT_ONOS_INTERFACE;
}
+ // Capture if they want to limit IP address selection to only IPv4 (default).
+ boolean allowIPv6 = (System.getenv(ONOS_ALLOW_IPV6) != null);
+
Function<NetworkInterface, IpAddress> ipLookup = nif -> {
- for (InetAddress address : Collections.list(nif.getInetAddresses())) {
- if (address.isSiteLocalAddress()) {
- return IpAddress.valueOf(address);
+ IpAddress fallback = null;
+
+ // nif can be null if the interface name specified doesn't exist on the node's host
+ if (nif != null) {
+ for (InetAddress address : Collections.list(nif.getInetAddresses())) {
+ if (address.isSiteLocalAddress() && (allowIPv6 || address instanceof Inet4Address)) {
+ return IpAddress.valueOf(address);
+ }
+ if (fallback == null && !address.isLoopbackAddress() && !address.isMulticastAddress()
+ && (allowIPv6 || address instanceof Inet4Address)) {
+ fallback = IpAddress.valueOf(address);
+ }
}
}
- return null;
+ return fallback;
};
try {
IpAddress ip = ipLookup.apply(NetworkInterface.getByName(useOnosInterface));
@@ -228,14 +242,17 @@ public class StaticClusterMetadataStore
return ip.toString();
}
for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
- ip = ipLookup.apply(nif);
- if (ip != null) {
- return ip.toString();
+ if (!nif.getName().equals(useOnosInterface)) {
+ 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();
}
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java
index 3e73d8f4..ca8eea37 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/config/impl/DistributedNetworkConfigStore.java
@@ -60,6 +60,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import static com.google.common.base.Preconditions.checkArgument;
import static org.onosproject.net.config.NetworkConfigEvent.Type.*;
/**
@@ -71,10 +72,12 @@ public class DistributedNetworkConfigStore
extends AbstractStore<NetworkConfigEvent, NetworkConfigStoreDelegate>
implements NetworkConfigStore {
- private static final int MAX_BACKOFF = 10;
-
private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final int MAX_BACKOFF = 10;
+ private static final String INVALID_CONFIG_JSON =
+ "JSON node does not contain valid configuration";
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@@ -187,8 +190,17 @@ public class DistributedNetworkConfigStore
@Override
public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
- return createConfig(subject, configClass,
- configs.putAndGet(key(subject, configClass), json).value());
+ // Create the configuration and validate it.
+ C config = createConfig(subject, configClass, json);
+ checkArgument(config.isValid(), INVALID_CONFIG_JSON);
+
+ // Insert the validated configuration and get it back.
+ Versioned<JsonNode> versioned = configs.putAndGet(key(subject, configClass), json);
+
+ // Re-create the config if for some reason what we attempted to put
+ // was supplanted by someone else already.
+ return versioned.value() == json ? config :
+ createConfig(subject, configClass, versioned.value());
}
@Override
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java
index 7e575b01..92db5b44 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/AsyncCachingConsistentMap.java
@@ -26,8 +26,12 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
- * Extension of DefaultAsyncConsistentMap that provides a weaker read consistency
+ * Extension of {@link DefaultAsyncConsistentMap} that provides a weaker read consistency
* guarantee in return for better read performance.
+ * <p>
+ * For read/write operations that are local to a node this map implementation provides
+ * guarantees similar to a ConsistentMap. However for read/write operations executed
+ * across multiple nodes this implementation only provides eventual consistency.
*
* @param <K> key type
* @param <V> value type
@@ -68,4 +72,10 @@ public class AsyncCachingConsistentMap<K, V> extends DefaultAsyncConsistentMap<K
}
return cache.getUnchecked(key);
}
+
+ @Override
+ protected void beforeUpdate(K key) {
+ super.beforeUpdate(key);
+ cache.invalidate(key);
+ }
} \ No newline at end of file
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 3e89635a..90d81ee7 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
@@ -55,6 +55,7 @@ import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.IdGenerator;
+import org.onosproject.persistence.PersistenceService;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.ecmap.EventuallyConsistentMapBuilderImpl;
import org.onosproject.store.service.AtomicCounterBuilder;
@@ -128,6 +129,9 @@ public class DatabaseManager implements StorageService, StorageAdminService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterCommunicationService clusterCommunicator;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PersistenceService persistenceService;
+
protected String nodeIdToUri(NodeId nodeId) {
ControllerNode node = clusterService.getNode(nodeId);
return String.format("onos://%s:%d", node.ip(), node.tcpPort());
@@ -312,7 +316,8 @@ public class DatabaseManager implements StorageService, StorageAdminService {
@Override
public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
return new EventuallyConsistentMapBuilderImpl<>(clusterService,
- clusterCommunicator);
+ clusterCommunicator,
+ persistenceService);
}
@Override
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java
index 0ea66861..c6d300c9 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultAsyncConsistentMap.java
@@ -405,6 +405,14 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V
.thenApply(v -> v.updated());
}
+ /**
+ * Pre-update hook for performing required checks/actions before going forward with an update operation.
+ * @param key map key.
+ */
+ protected void beforeUpdate(K key) {
+ checkIfUnmodifiable();
+ }
+
private Map.Entry<K, Versioned<V>> mapRawEntry(Map.Entry<String, Versioned<byte[]>> e) {
return Maps.immutableEntry(dK(e.getKey()), e.getValue().<V>map(serializer::decode));
}
@@ -413,7 +421,7 @@ public class DefaultAsyncConsistentMap<K, V> implements AsyncConsistentMap<K, V
Match<V> oldValueMatch,
Match<Long> oldVersionMatch,
V value) {
- checkIfUnmodifiable();
+ beforeUpdate(key);
return database.mapUpdate(name,
keyCache.getUnchecked(key),
oldValueMatch.map(serializer::encode),
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java
index a553ffff..eb98c829 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapBuilderImpl.java
@@ -18,6 +18,7 @@ package org.onosproject.store.ecmap;
import org.onlab.util.KryoNamespace;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId;
+import org.onosproject.persistence.PersistenceService;
import org.onosproject.store.Timestamp;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.service.EventuallyConsistentMap;
@@ -52,6 +53,8 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
private TimeUnit antiEntropyTimeUnit = TimeUnit.SECONDS;
private boolean convergeFaster = false;
private boolean persistent = false;
+ private boolean persistentMap = false;
+ private final PersistenceService persistenceService;
/**
* Creates a new eventually consistent map builder.
@@ -60,7 +63,9 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
* @param clusterCommunicator cluster communication service
*/
public EventuallyConsistentMapBuilderImpl(ClusterService clusterService,
- ClusterCommunicationService clusterCommunicator) {
+ ClusterCommunicationService clusterCommunicator,
+ PersistenceService persistenceService) {
+ this.persistenceService = persistenceService;
this.clusterService = checkNotNull(clusterService);
this.clusterCommunicator = checkNotNull(clusterCommunicator);
}
@@ -133,6 +138,7 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
@Override
public EventuallyConsistentMapBuilder<K, V> withPersistence() {
+ checkNotNull(this.persistenceService);
persistent = true;
return this;
}
@@ -156,6 +162,7 @@ public class EventuallyConsistentMapBuilderImpl<K, V>
antiEntropyPeriod,
antiEntropyTimeUnit,
convergeFaster,
- persistent);
+ persistent,
+ persistenceService);
}
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java
index f1e0dbd4..b5ea52e0 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/EventuallyConsistentMapImpl.java
@@ -28,6 +28,7 @@ import org.onlab.util.SlidingWindowCounter;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
+import org.onosproject.persistence.PersistenceService;
import org.onosproject.store.Timestamp;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.cluster.messaging.MessageSubject;
@@ -37,6 +38,7 @@ import org.onosproject.store.serializers.KryoSerializer;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapEvent;
import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.WallClockTimestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -81,6 +83,7 @@ public class EventuallyConsistentMapImpl<K, V>
private final ClusterCommunicationService clusterCommunicator;
private final KryoSerializer serializer;
private final NodeId localNodeId;
+ private final PersistenceService persistenceService;
private final BiFunction<K, V, Timestamp> timestampProvider;
@@ -116,7 +119,9 @@ public class EventuallyConsistentMapImpl<K, V>
private SlidingWindowCounter counter = new SlidingWindowCounter(WINDOW_SIZE);
private final boolean persistent;
- private final PersistentStore<K, V> persistentStore;
+
+ private static final String PERSISTENT_LOCAL_MAP_NAME = "itemsMap";
+
/**
* Creates a new eventually consistent map shared amongst multiple instances.
@@ -158,9 +163,32 @@ public class EventuallyConsistentMapImpl<K, V>
long antiEntropyPeriod,
TimeUnit antiEntropyTimeUnit,
boolean convergeFaster,
- boolean persistent) {
+ boolean persistent,
+ PersistenceService persistenceService) {
this.mapName = mapName;
- items = Maps.newConcurrentMap();
+ this.serializer = createSerializer(serializerBuilder);
+ this.persistenceService = persistenceService;
+ this.persistent =
+ persistent;
+ if (persistent) {
+ items = this.persistenceService.<K, MapValue<V>>persistentMapBuilder()
+ .withName(PERSISTENT_LOCAL_MAP_NAME)
+ .withSerializer(new Serializer() {
+
+ @Override
+ public <T> byte[] encode(T object) {
+ return EventuallyConsistentMapImpl.this.serializer.encode(object);
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ return EventuallyConsistentMapImpl.this.serializer.decode(bytes);
+ }
+ })
+ .build();
+ } else {
+ items = Maps.newConcurrentMap();
+ }
senderPending = Maps.newConcurrentMap();
destroyedMessage = mapName + ERROR_DESTROYED;
@@ -168,8 +196,6 @@ public class EventuallyConsistentMapImpl<K, V>
this.clusterCommunicator = clusterCommunicator;
this.localNodeId = clusterService.getLocalNode().id();
- this.serializer = createSerializer(serializerBuilder);
-
this.timestampProvider = timestampProvider;
if (peerUpdateFunction != null) {
@@ -198,20 +224,6 @@ public class EventuallyConsistentMapImpl<K, V>
newFixedThreadPool(8, groupedThreads("onos/ecm", mapName + "-publish-%d"));
}
- this.persistent = persistent;
-
- if (this.persistent) {
- String dataDirectory = System.getProperty("karaf.data", "./data");
- String filename = dataDirectory + "/" + "mapdb-ecm-" + mapName;
-
- ExecutorService dbExecutor =
- newFixedThreadPool(1, groupedThreads("onos/ecm", mapName + "-dbwriter"));
-
- persistentStore = new MapDbPersistentStore<>(filename, dbExecutor, serializer);
- persistentStore.readInto(items);
- } else {
- this.persistentStore = null;
- }
if (backgroundExecutor != null) {
this.backgroundExecutor = backgroundExecutor;
@@ -373,15 +385,6 @@ public class EventuallyConsistentMapImpl<K, V>
return existing;
}
});
- if (updated.get()) {
- if (persistent) {
- if (tombstone.isPresent()) {
- persistentStore.update(key, tombstone.get());
- } else {
- persistentStore.remove(key);
- }
- }
- }
return previousValue.get();
}
@@ -455,6 +458,7 @@ public class EventuallyConsistentMapImpl<K, V>
/**
* Returns true if newValue was accepted i.e. map is updated.
+ *
* @param key key
* @param newValue proposed new value
* @return true if update happened; false if map already contains a more recent value for the key
@@ -473,9 +477,6 @@ public class EventuallyConsistentMapImpl<K, V>
}
return existing;
});
- if (updated.get() && persistent) {
- persistentStore.update(key, newValue);
- }
return updated.get();
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java
index 391a88f7..20124576 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/host/impl/ECHostStore.java
@@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.onosproject.net.DefaultAnnotations.merge;
import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
+import static org.onosproject.net.host.HostEvent.Type.HOST_MOVED;
import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED;
import static org.onosproject.net.host.HostEvent.Type.HOST_UPDATED;
import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
@@ -88,7 +89,7 @@ public class ECHostStore
private EventuallyConsistentMap<HostId, DefaultHost> hosts;
- private final ConcurrentHashMap<HostId, HostLocation> locations =
+ private final ConcurrentHashMap<HostId, DefaultHost> prevHosts =
new ConcurrentHashMap<>();
private EventuallyConsistentMapListener<HostId, DefaultHost> hostLocationTracker =
@@ -114,7 +115,7 @@ public class ECHostStore
public void deactivate() {
hosts.removeListener(hostLocationTracker);
hosts.destroy();
- locations.clear();
+ prevHosts.clear();
log.info("Stopped");
}
@@ -253,16 +254,16 @@ public class ECHostStore
public void event(EventuallyConsistentMapEvent<HostId, DefaultHost> event) {
DefaultHost host = checkNotNull(event.value());
if (event.type() == PUT) {
- HostLocation prevLocation = locations.put(host.id(), host.location());
- if (prevLocation == null) {
+ Host prevHost = prevHosts.put(host.id(), host);
+ if (prevHost == null) {
notifyDelegate(new HostEvent(HOST_ADDED, host));
- } else if (!Objects.equals(prevLocation, host.location())) {
- notifyDelegate(new HostEvent(host, prevLocation));
- } else {
- notifyDelegate(new HostEvent(HOST_UPDATED, host));
+ } else if (!Objects.equals(prevHost.location(), host.location())) {
+ notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost));
+ } else if (!Objects.equals(prevHost, host)) {
+ notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost));
}
} else if (event.type() == REMOVE) {
- if (locations.remove(host.id()) != null) {
+ if (prevHosts.remove(host.id()) != null) {
notifyDelegate(new HostEvent(HOST_REMOVED, host));
}
}
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 4d9e3cbf..0335ba5d 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
@@ -264,7 +264,7 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour
}
return children.value().stream()
- .filter(x -> x.lastComponent().getClass().equals(cls))
+ .filter(x -> x.last().getClass().equals(cls))
.filter(consumerMap::containsKey)
.collect(Collectors.toList());
}
@@ -344,7 +344,7 @@ public class ConsistentResourceStore extends AbstractStore<ResourceEvent, Resour
*/
private boolean isRegistered(TransactionalMap<ResourcePath, List<ResourcePath>> map, ResourcePath resource) {
// root is always regarded to be registered
- if (resource.isRoot()) {
+ if (!resource.parent().isPresent()) {
return true;
}
diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java
index ccf6ee71..ef8d9924 100644
--- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java
+++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java
@@ -42,6 +42,7 @@ import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.event.AbstractEvent;
+import org.onosproject.persistence.impl.PersistenceManager;
import org.onosproject.store.Timestamp;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
@@ -81,6 +82,7 @@ public class EventuallyConsistentMapImplTest {
private EventuallyConsistentMap<String, String> ecMap;
+ private PersistenceManager persistenceService;
private ClusterService clusterService;
private ClusterCommunicationService clusterCommunicator;
private SequentialClockService<String, String> clockService;
@@ -136,6 +138,8 @@ public class EventuallyConsistentMapImplTest {
clusterCommunicator = createMock(ClusterCommunicationService.class);
+ persistenceService = new PersistenceManager();
+ persistenceService.activate();
// Add expectation for adding cluster message subscribers which
// delegate to our ClusterCommunicationService implementation. This
// allows us to get a reference to the map's internal cluster message
@@ -153,11 +157,12 @@ public class EventuallyConsistentMapImplTest {
.register(TestTimestamp.class);
ecMap = new EventuallyConsistentMapBuilderImpl<String, String>(
- clusterService, clusterCommunicator)
+ clusterService, clusterCommunicator, persistenceService)
.withName(MAP_NAME)
.withSerializer(serializer)
.withTimestampProvider((k, v) -> clockService.getTimestamp(k, v))
.withCommunicationExecutor(MoreExecutors.newDirectExecutorService())
+ .withPersistence()
.build();
// Reset ready for tests to add their own expectations
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 b2199f70..6f96498f 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
@@ -416,6 +416,8 @@ public final class KryoNamespaces {
BandwidthResourceAllocation.class,
LambdaResourceAllocation.class,
ResourcePath.class,
+ ResourcePath.Discrete.class,
+ ResourcePath.Continuous.class,
ResourceAllocation.class,
// Constraints
LambdaConstraint.class,
diff --git a/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java b/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
index 97ccb836..11a62d4e 100644
--- a/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
+++ b/framework/src/onos/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
@@ -373,13 +373,13 @@ public class KryoSerializerTest {
@Test
public void testResourcePath() {
- testSerializedEquals(new ResourcePath(LinkKey.linkKey(CP1, CP2), VLAN1));
+ testSerializedEquals(ResourcePath.discrete(LinkKey.linkKey(CP1, CP2), VLAN1));
}
@Test
public void testResourceAllocation() {
testSerializedEquals(new org.onosproject.net.newresource.ResourceAllocation(
- new ResourcePath(LinkKey.linkKey(CP1, CP2), VLAN1),
+ ResourcePath.discrete(LinkKey.linkKey(CP1, CP2), VLAN1),
IntentId.valueOf(30)));
}