diff options
Diffstat (limited to 'framework/src/onos/core')
153 files changed, 2302 insertions, 791 deletions
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java index 2561280b..e8ff9ec4 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java @@ -86,4 +86,11 @@ public interface ApplicationDescription { * @return application features */ List<String> features(); + + /** + * Returns list of required application names. + * + * @return list of application names + */ + List<String> requiredApps(); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java index 73dcc86c..1e543b85 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationService.java @@ -67,4 +67,11 @@ public interface ApplicationService */ Set<Permission> getPermissions(ApplicationId appId); + /** + * Registers application pre-deactivation processing hook. + * + * @param appId application identifier + * @param hook pre-deactivation hook + */ + void registerDeactivateHook(ApplicationId appId, Runnable hook); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java index b3cdc43e..0a1f0727 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/ApplicationStore.java @@ -76,7 +76,7 @@ public interface ApplicationStore extends Store<ApplicationEvent, ApplicationSto void remove(ApplicationId appId); /** - * Mark the application as actived. + * Mark the application as active. * * @param appId application identifier */ diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java index 710d0f9c..569183a7 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java @@ -41,6 +41,7 @@ public class DefaultApplicationDescription implements ApplicationDescription { private final Set<Permission> permissions; private final Optional<URI> featuresRepo; private final List<String> features; + private final List<String> requiredApps; /** * Creates a new application descriptor using the supplied data. @@ -53,11 +54,13 @@ public class DefaultApplicationDescription implements ApplicationDescription { * @param permissions requested permissions * @param featuresRepo optional features repo URI * @param features application features + * @param requiredApps list of required application names */ public DefaultApplicationDescription(String name, Version version, String description, String origin, ApplicationRole role, Set<Permission> permissions, - URI featuresRepo, List<String> features) { + URI featuresRepo, List<String> features, + List<String> requiredApps) { this.name = checkNotNull(name, "Name cannot be null"); this.version = checkNotNull(version, "Version cannot be null"); this.description = checkNotNull(description, "Description cannot be null"); @@ -66,6 +69,7 @@ public class DefaultApplicationDescription implements ApplicationDescription { this.permissions = checkNotNull(permissions, "Permissions cannot be null"); this.featuresRepo = Optional.ofNullable(featuresRepo); this.features = checkNotNull(features, "Features cannot be null"); + this.requiredApps = checkNotNull(requiredApps, "Required apps cannot be null"); checkArgument(!features.isEmpty(), "There must be at least one feature"); } @@ -110,6 +114,11 @@ public class DefaultApplicationDescription implements ApplicationDescription { } @Override + public List<String> requiredApps() { + return requiredApps; + } + + @Override public String toString() { return toStringHelper(this) .add("name", name) @@ -120,6 +129,7 @@ public class DefaultApplicationDescription implements ApplicationDescription { .add("permissions", permissions) .add("featuresRepo", featuresRepo) .add("features", features) + .add("requiredApps", requiredApps) .toString(); } } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java index 36cd22b5..f1b602e8 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java @@ -245,7 +245,7 @@ public final class ConfigProperty { @Override public int hashCode() { - return Objects.hash(name); + return name.hashCode(); } /** diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java index 5f3e0e19..3787daa5 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/DefaultControllerNode.java @@ -20,6 +20,7 @@ import org.onlab.packet.IpAddress; import java.util.Objects; import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; /** * Default implementation of a controller instance descriptor. @@ -57,7 +58,7 @@ public class DefaultControllerNode implements ControllerNode { * @param tcpPort TCP port */ public DefaultControllerNode(NodeId id, IpAddress ip, int tcpPort) { - this.id = id; + this.id = checkNotNull(id); this.ip = ip; this.tcpPort = tcpPort; } @@ -79,7 +80,7 @@ public class DefaultControllerNode implements ControllerNode { @Override public int hashCode() { - return Objects.hash(id); + return id.hashCode(); } @Override 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 6cfb42c7..e5ab9dc8 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 @@ -35,7 +35,7 @@ public class NodeId implements Comparable<NodeId> { @Override public int hashCode() { - return Objects.hash(id); + return id.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java index fca53843..ea2eab9b 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Application.java @@ -84,4 +84,11 @@ public interface Application { * @return application features */ List<String> features(); + + /** + * Returns list of required application names. + * + * @return list of application names + */ + List<String> requiredApps(); } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java index 303ad395..0825a6d1 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/CoreService.java @@ -50,6 +50,7 @@ public interface CoreService { /** * Returns an existing application id from a given id. + * * @param id the short value of the id * @return an application id */ @@ -57,6 +58,7 @@ public interface CoreService { /** * Returns an existing application id from a given id. + * * @param name the name portion of the ID to look up * @return an application id */ @@ -67,10 +69,21 @@ public interface CoreService { * to follow the reverse DNS convention, e.g. * {@code org.flying.circus.app} * - * @param identifier string identifier + * @param name string identifier + * @return the application id + */ + ApplicationId registerApplication(String name); + + /** + * Registers a new application by its name, which is expected + * to follow the reverse DNS convention, e.g. + * {@code org.flying.circus.app}, along with its pre-deactivation hook. + * + * @param name string identifier + * @param preDeactivate pre-deactivation hook * @return the application id */ - ApplicationId registerApplication(String identifier); + ApplicationId registerApplication(String name, Runnable preDeactivate); /** * Returns an id generator for a given topic. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java index d8062ddf..c3515638 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplication.java @@ -40,6 +40,7 @@ public class DefaultApplication implements Application { private final Set<Permission> permissions; private final Optional<URI> featuresRepo; private final List<String> features; + private final List<String> requiredApps; /** * Creates a new application descriptor using the supplied data. @@ -52,11 +53,13 @@ public class DefaultApplication implements Application { * @param permissions requested permissions * @param featuresRepo optional features repo URI * @param features application features + * @param requiredApps list of required application names */ public DefaultApplication(ApplicationId appId, Version version, String description, String origin, ApplicationRole role, Set<Permission> permissions, - Optional<URI> featuresRepo, List<String> features) { + Optional<URI> featuresRepo, List<String> features, + List<String> requiredApps) { this.appId = checkNotNull(appId, "ID cannot be null"); this.version = checkNotNull(version, "Version cannot be null"); this.description = checkNotNull(description, "Description cannot be null"); @@ -65,6 +68,7 @@ public class DefaultApplication implements Application { this.permissions = checkNotNull(permissions, "Permissions cannot be null"); this.featuresRepo = checkNotNull(featuresRepo, "Features repo cannot be null"); this.features = checkNotNull(features, "Features cannot be null"); + this.requiredApps = checkNotNull(requiredApps, "Required apps cannot be null"); checkArgument(!features.isEmpty(), "There must be at least one feature"); } @@ -109,9 +113,14 @@ public class DefaultApplication implements Application { } @Override + public List<String> requiredApps() { + return requiredApps; + } + + @Override public int hashCode() { return Objects.hash(appId, version, description, origin, role, permissions, - featuresRepo, features); + featuresRepo, features, requiredApps); } @Override @@ -130,7 +139,8 @@ public class DefaultApplication implements Application { Objects.equals(this.role, other.role) && Objects.equals(this.permissions, other.permissions) && Objects.equals(this.featuresRepo, other.featuresRepo) && - Objects.equals(this.features, other.features); + Objects.equals(this.features, other.features) && + Objects.equals(this.requiredApps, other.requiredApps); } @Override @@ -144,6 +154,7 @@ public class DefaultApplication implements Application { .add("permissions", permissions) .add("featuresRepo", featuresRepo) .add("features", features) + .add("requiredApps", requiredApps) .toString(); } } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java index c7b5b2da..aedfb0d3 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java @@ -58,7 +58,7 @@ public class DefaultApplicationId implements ApplicationId { @Override public int hashCode() { - return Objects.hash(id); + return Short.hashCode(id); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java index 9fa8d2b6..243e5216 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java @@ -42,7 +42,7 @@ public class DefaultGroupId implements GroupId { @Override public int hashCode() { - return Objects.hash(id); + return id; } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java index a5377016..06e9e206 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/core/Version.java @@ -127,7 +127,7 @@ public final class Version { @Override public int hashCode() { - return Objects.hash(format); + return format.hashCode(); } @Override 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/DefaultPath.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java index a4789cac..2da2463a 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DefaultPath.java @@ -88,7 +88,7 @@ public class DefaultPath extends DefaultLink implements Path { @Override public int hashCode() { - return Objects.hash(links); + return links.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java index 5331342e..e2c1214f 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/DeviceId.java @@ -75,7 +75,7 @@ public final class DeviceId extends ElementId { @Override public int hashCode() { - return Objects.hash(str); + return str.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java index 03e6dba9..8c9b1349 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/PortNumber.java @@ -15,6 +15,16 @@ */ package org.onosproject.net; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; import com.google.common.primitives.UnsignedLongs; /** @@ -26,8 +36,7 @@ public final class PortNumber { // TODO: revisit the max and the logical port value assignments - private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1; - + static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1; static final long IN_PORT_NUMBER = -8L; static final long TABLE_NUMBER = -7L; @@ -37,6 +46,39 @@ public final class PortNumber { static final long LOCAL_NUMBER = -2L; static final long CONTROLLER_NUMBER = -3L; + /** + * Logical PortNumbers. + */ + public static enum Logical { + IN_PORT(IN_PORT_NUMBER), + TABLE(TABLE_NUMBER), + NORMAL(NORMAL_NUMBER), + FLOOD(FLOOD_NUMBER), + ALL(ALL_NUMBER), + LOCAL(LOCAL_NUMBER), + CONTROLLER(CONTROLLER_NUMBER); + + private final long number; + private final PortNumber instance; + + public long number() { + return number; + } + + /** + * PortNumber instance for the logical port. + * @return {@link PortNumber} + */ + public PortNumber instance() { + return instance; + } + + Logical(long number) { + this.number = number; + this.instance = new PortNumber(number); + } + } + public static final PortNumber IN_PORT = new PortNumber(IN_PORT_NUMBER); public static final PortNumber TABLE = new PortNumber(TABLE_NUMBER); public static final PortNumber NORMAL = new PortNumber(NORMAL_NUMBER); @@ -45,6 +87,15 @@ public final class PortNumber { public static final PortNumber LOCAL = new PortNumber(LOCAL_NUMBER); public static final PortNumber CONTROLLER = new PortNumber(CONTROLLER_NUMBER); + // lazily populated Logical port number to PortNumber + static final Supplier<Map<Long, Logical>> LOGICAL = Suppliers.memoize(() -> { + Builder<Long, Logical> builder = ImmutableMap.<Long, Logical>builder(); + for (Logical lp : Logical.values()) { + builder.put(lp.number(), lp); + } + return builder.build(); + }); + private final long number; private final String name; private final boolean hasName; @@ -136,30 +187,68 @@ public final class PortNumber { } private String decodeLogicalPort() { - if (number == CONTROLLER_NUMBER) { - return "CONTROLLER"; - } else if (number == LOCAL_NUMBER) { - return "LOCAL"; - } else if (number == ALL_NUMBER) { - return "ALL"; - } else if (number == FLOOD_NUMBER) { - return "FLOOD"; - } else if (number == NORMAL_NUMBER) { - return "NORMAL"; - } else if (number == TABLE_NUMBER) { - return "TABLE"; - } else if (number == IN_PORT_NUMBER) { - return "IN_PORT"; + Logical logical = LOGICAL.get().get(number); + if (logical != null) { + // enum name + return logical.toString(); + } + return String.format("UNKNOWN(%s)", UnsignedLongs.toString(number)); + } + + + /** + * Regular expression to match String representation of named PortNumber. + * + * Format: "[name](num:unsigned decimal string)" + */ + private static final Pattern NAMED = Pattern.compile("^\\[(?<name>.*)\\]\\((?<num>\\d+)\\)$"); + + private static boolean isAsciiDecimal(char c) { + return '0' <= c && c <= '9'; + } + + /** + * Returns PortNumber instance from String representation. + * + * @param s String representation equivalent to {@link PortNumber#toString()} + * @return {@link PortNumber} instance + * @throws IllegalArgumentException if given String was malformed + */ + public static PortNumber fromString(String s) { + checkNotNull(s); + checkArgument(!s.isEmpty(), "cannot be empty"); + + if (isAsciiDecimal(s.charAt(0))) { + // unsigned decimal string + return portNumber(s); + } else if (s.startsWith("[")) { + // named PortNumber + Matcher matcher = NAMED.matcher(s); + checkArgument(matcher.matches(), "Invalid named PortNumber %s", s); + + String name = matcher.group("name"); + String num = matcher.group("num"); + return portNumber(UnsignedLongs.parseUnsignedLong(num), name); + } + + // Logical + if (s.startsWith("UNKNOWN(") && s.endsWith(")")) { + return portNumber(s.substring("UNKNOWN(".length(), s.length() - 1)); + } else { + return Logical.valueOf(s).instance; } - return "UNKNOWN"; } @Override public String toString() { - if (!isLogical()) { - return name; - } else { + if (isLogical()) { return decodeLogicalPort(); + } else if (hasName()) { + // named port + return String.format("[%s](%d)", name, number); + } else { + // unsigned decimal string + return name; } } 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/behaviour/BridgeName.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java index 3f782954..a15217c6 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeName.java @@ -52,7 +52,7 @@ public final class BridgeName { @Override public int hashCode() { - return Objects.hash(name); + return name.hashCode(); } @Override 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 3a8c8c1f..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. @@ -71,7 +72,7 @@ public class DefaultDeviceDescription extends AbstractDescription */ public DefaultDeviceDescription(DeviceDescription base, SparseAnnotations... annotations) { - this(base.deviceURI(), base.type(), base.manufacturer(), + this(base.deviceUri(), base.type(), base.manufacturer(), base.hwVersion(), base.swVersion(), base.serialNumber(), base.chassisId(), annotations); } @@ -83,13 +84,13 @@ public class DefaultDeviceDescription extends AbstractDescription * @param annotations Annotations to use. */ public DefaultDeviceDescription(DeviceDescription base, Type type, SparseAnnotations... annotations) { - this(base.deviceURI(), type, base.manufacturer(), + this(base.deviceUri(), type, base.manufacturer(), base.hwVersion(), base.swVersion(), base.serialNumber(), base.chassisId(), annotations); } @Override - public URI deviceURI() { + public URI deviceUri() { return uri; } @@ -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/device/DeviceDescription.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java index 64b84b5a..f206b080 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/device/DeviceDescription.java @@ -33,7 +33,7 @@ public interface DeviceDescription extends Description { * * @return provider specific URI for the device */ - URI deviceURI(); + URI deviceUri(); /** * Returns the type of the infrastructure device. 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/DefaultTrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java index 6beeecc9..4615a82b 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 @@ -388,7 +388,12 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { @Override public Builder setQueue(long queueId) { - return add(Instructions.setQueue(queueId)); + return add(Instructions.setQueue(queueId, null)); + } + + @Override + public Builder setQueue(long queueId, PortNumber port) { + return add(Instructions.setQueue(queueId, port)); } @Override 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/TrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java index b14ab99c..f1a676ab 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 @@ -271,6 +271,15 @@ public interface TrafficTreatment { Builder setQueue(long queueId); /** + * Sets the Queue ID for a specific port. + * + * @param queueId a queue ID + * @param port a port number + * @return a treatment builder + */ + Builder setQueue(long queueId, PortNumber port); + + /** * Sets a meter to be used by this flow. * * @param meterId a meter id diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpHaCriterion.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpHaCriterion.java new file mode 100644 index 00000000..71269dd1 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/criteria/ArpHaCriterion.java @@ -0,0 +1,83 @@ +/* + * 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.criteria; + +import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Objects; + +import org.onlab.packet.MacAddress; + +/** + * Implementation of arp_eth_src address or arp_eth_dst address criterion. + */ +public final class ArpHaCriterion implements Criterion { + private final MacAddress mac; + private final Type type; + + /** + * Constructor. + * + * @param mac the MAC Address to match. + * @param type the match type. Should be one of the following: + * Type.ARP_SHA, Type.ARP_THA + */ + ArpHaCriterion(MacAddress mac, Type type) { + checkNotNull(mac, "mac cannot be null"); + checkNotNull(type, "type cannot be null"); + this.mac = mac; + this.type = type; + } + + @Override + public Type type() { + return this.type; + } + + /** + * Gets the MAC Address to match. + * + * @return the MAC Address to match + */ + public MacAddress mac() { + return this.mac; + } + + @Override + public String toString() { + return toStringHelper(type().toString()) + .add("mac", mac).toString(); + } + + @Override + public int hashCode() { + return Objects.hash(type().ordinal(), mac); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof ArpHaCriterion) { + ArpHaCriterion that = (ArpHaCriterion) obj; + return Objects.equals(mac, that.mac) && + Objects.equals(type, that.type); + } + return false; + } +}
\ No newline at end of file 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 778d50a5..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,15 +510,45 @@ 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) { return new ArpPaCriterion(ip, Type.ARP_TPA); } + /** + * Creates a match on IPv4 source field using the specified 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/flow/instructions/Instructions.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java index aad407c8..126e722e 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 @@ -15,6 +15,7 @@ */ package org.onosproject.net.flow.instructions; +import com.google.common.base.MoreObjects; import org.onlab.packet.EthType; import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; @@ -99,11 +100,12 @@ public final class Instructions { * Creates a set-queue instruction. * * @param queueId Queue Id + * @param port Port number * @return set-queue instruction */ - public static SetQueueInstruction setQueue(final long queueId) { + public static SetQueueInstruction setQueue(final long queueId, final PortNumber port) { checkNotNull(queueId, "queue ID cannot be null"); - return new SetQueueInstruction(queueId); + return new SetQueueInstruction(queueId, port); } public static MeterInstruction meterTraffic(final MeterId meterId) { @@ -514,7 +516,7 @@ public final class Instructions { @Override public int hashCode() { - return Objects.hash(type().ordinal()); + return type().ordinal(); } @Override @@ -548,7 +550,7 @@ public final class Instructions { @Override public int hashCode() { - return Objects.hash(type().ordinal()); + return type().ordinal(); } @Override @@ -628,7 +630,8 @@ public final class Instructions { @Override public String toString() { return toStringHelper(type().toString()) - .add("group ID", groupId.id()).toString(); + .addValue("group ID=0x" + Integer.toHexString(groupId.id())) + .toString(); } @Override @@ -655,15 +658,26 @@ public final class Instructions { */ public static final class SetQueueInstruction implements Instruction { private final long queueId; + private final PortNumber port; private SetQueueInstruction(long queueId) { this.queueId = queueId; + this.port = null; + } + + private SetQueueInstruction(long queueId, PortNumber port) { + this.queueId = queueId; + this.port = port; } public long queueId() { return queueId; } + public PortNumber port() { + return port; + } + @Override public Type type() { return Type.QUEUE; @@ -671,13 +685,18 @@ public final class Instructions { @Override public String toString() { - return toStringHelper(type().toString()) - .add("queueId", queueId).toString(); + MoreObjects.ToStringHelper toStringHelper = toStringHelper(type().toString()); + toStringHelper.add("queueId", queueId); + + if (port() != null) { + toStringHelper.add("port", port); + } + return toStringHelper.toString(); } @Override public int hashCode() { - return Objects.hash(type().ordinal(), queueId); + return Objects.hash(type().ordinal(), queueId, port); } @Override @@ -687,7 +706,7 @@ public final class Instructions { } if (obj instanceof SetQueueInstruction) { SetQueueInstruction that = (SetQueueInstruction) obj; - return Objects.equals(queueId, that.queueId); + return Objects.equals(queueId, that.queueId) && Objects.equals(port, that.port); } return false; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java index a6e5903c..4af3d168 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L0ModificationInstruction.java @@ -114,7 +114,7 @@ public abstract class L0ModificationInstruction implements Instruction { @Override public int hashCode() { - return Objects.hash(lambda); + return lambda.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L1ModificationInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L1ModificationInstruction.java index c6847d1c..b72dd7bc 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L1ModificationInstruction.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/L1ModificationInstruction.java @@ -62,7 +62,7 @@ public abstract class L1ModificationInstruction implements Instruction { @Override public int hashCode() { - return Objects.hash(oduSignalId); + return oduSignalId.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java index 546a4513..97f8aedf 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java @@ -186,7 +186,7 @@ public class DefaultGroup extends DefaultGroupDescription */ @Override public int hashCode() { - return super.hashCode() + Objects.hash(id); + return Objects.hash(super.hashCode(), id); } /* 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 98329df0..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 @@ -15,9 +15,12 @@ */ package org.onosproject.net.host; +import org.joda.time.LocalDateTime; import org.onosproject.event.AbstractEvent; import org.onosproject.net.Host; +import static com.google.common.base.MoreObjects.toStringHelper; + /** * Describes end-station host event. */ @@ -48,6 +51,8 @@ public class HostEvent extends AbstractEvent<HostEvent.Type, Host> { HOST_MOVED } + private Host prevSubject; + /** * Creates an event of a given type and for the specified host and the * current time. @@ -70,4 +75,39 @@ public class HostEvent extends AbstractEvent<HostEvent.Type, Host> { super(type, host, time); } + /** + * 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 prevSubject previous host subject + */ + 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 subject in this host event. + * + * @return the previous subject, or null if previous subject is not + * specified. + */ + public Host prevSubject() { + return this.prevSubject; + } + + @Override + public String toString() { + return toStringHelper(this) + .add("time", new LocalDateTime(time())) + .add("type", type()) + .add("subject", subject()) + .add("prevSubject", prevSubject()) + .toString(); + } } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java index caa5fbb9..4548c44d 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/MplsPathIntent.java @@ -42,6 +42,7 @@ public final class MplsPathIntent extends PathIntent { * ports and using the specified explicit path. * * @param appId application identifier + * @param key intent key * @param selector traffic selector * @param treatment treatment * @param path traversed links @@ -51,11 +52,11 @@ public final class MplsPathIntent extends PathIntent { * @param priority priority to use for flows generated by this intent * @throws NullPointerException {@code path} is null */ - private MplsPathIntent(ApplicationId appId, TrafficSelector selector, + private MplsPathIntent(ApplicationId appId, Key key, TrafficSelector selector, TrafficTreatment treatment, Path path, Optional<MplsLabel> ingressLabel, Optional<MplsLabel> egressLabel, List<Constraint> constraints, int priority) { - super(appId, selector, treatment, path, constraints, + super(appId, key, selector, treatment, path, constraints, priority); this.ingressLabel = checkNotNull(ingressLabel); @@ -149,6 +150,7 @@ public final class MplsPathIntent extends PathIntent { return new MplsPathIntent( appId, + key, selector, treatment, path, diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java index 0c831fd5..9bf137a1 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java @@ -42,6 +42,7 @@ public class PathIntent extends ConnectivityIntent { * ports and using the specified explicit path. * * @param appId application identifier + * @param key intent key * @param selector traffic selector * @param treatment treatment * @param path traversed links @@ -50,12 +51,13 @@ public class PathIntent extends ConnectivityIntent { * @throws NullPointerException {@code path} is null */ protected PathIntent(ApplicationId appId, + Key key, TrafficSelector selector, TrafficTreatment treatment, Path path, List<Constraint> constraints, int priority) { - super(appId, null, resources(path.links()), selector, treatment, constraints, + super(appId, key, resources(path.links()), selector, treatment, constraints, priority); PathIntent.validate(path.links()); this.path = path; @@ -138,6 +140,7 @@ public class PathIntent extends ConnectivityIntent { return new PathIntent( appId, + key, selector, treatment, path, @@ -184,6 +187,7 @@ public class PathIntent extends ConnectivityIntent { public String toString() { return MoreObjects.toStringHelper(getClass()) .add("id", id()) + .add("key", key()) .add("appId", appId()) .add("priority", priority()) .add("resources", resources()) 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 20ccb55d..444feee4 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 @@ -87,7 +87,7 @@ public final class BandwidthConstraint extends BooleanConstraint { @Override public int hashCode() { - return Objects.hash(bandwidth); + return bandwidth.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java index 9dd813b2..7811a004 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LambdaConstraint.java @@ -69,7 +69,7 @@ public class LambdaConstraint extends BooleanConstraint { @Override public int hashCode() { - return Objects.hash(lambda); + return Objects.hashCode(lambda); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java index 54eb4ea5..aecef879 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/LatencyConstraint.java @@ -67,7 +67,7 @@ public class LatencyConstraint implements Constraint { @Override public int hashCode() { - return Objects.hash(latency); + return latency.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java index cb1e6b2b..ca4f3fd3 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/ObstacleConstraint.java @@ -66,7 +66,7 @@ public class ObstacleConstraint extends BooleanConstraint { @Override public int hashCode() { - return Objects.hash(obstacles); + return obstacles.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java index 1acf6dfe..4839feec 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/WaypointConstraint.java @@ -91,7 +91,7 @@ public class WaypointConstraint implements Constraint { @Override public int hashCode() { - return Objects.hash(waypoints); + return waypoints.hashCode(); } @Override 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/ResourceAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java index e94ee452..cdcd4072 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceAdminService.java @@ -26,7 +26,7 @@ import java.util.List; @Beta public interface ResourceAdminService { /** - * Register resources as the children of the parent resource path. + * Registers resources as the children of the parent resource path. * * @param parent parent resource path under which the resource are registered * @param children resources to be registered as the children of the parent @@ -39,7 +39,7 @@ public interface ResourceAdminService { } /** - * Register resources as the children of the parent resource path. + * Registers resources as the children of the parent resource path. * * @param parent parent resource path under which the resource are registered * @param children resources to be registered as the children of the parent @@ -50,7 +50,7 @@ public interface ResourceAdminService { <T> boolean registerResources(ResourcePath parent, List<T> children); /** - * Unregister resources as the children of the parent resource path. + * Unregisters resources as the children of the parent resource path. * * @param parent parent resource path under which the resource are unregistered * @param children resources to be unregistered as the children of the parent @@ -63,7 +63,7 @@ public interface ResourceAdminService { } /** - * Unregister resources as the children of the parent resource path. + * Unregisters resources as the children of the parent resource path. * * @param parent parent resource path under which the resource are unregistered * @param children resources to be unregistered as the children of the parent diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceEvent.java new file mode 100644 index 00000000..98abf301 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceEvent.java @@ -0,0 +1,54 @@ +/* + * 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.newresource; + +import com.google.common.annotations.Beta; +import org.onosproject.event.AbstractEvent; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Describes an event related to a resource. + */ +@Beta +public final class ResourceEvent extends AbstractEvent<ResourceEvent.Type, ResourcePath> { + + /** + * Type of resource events. + */ + @Beta + public enum Type { + /** + * Signifies that a new resource has been detected. + */ + RESOURCE_ADDED, + + /** + * Signifies that a resource has been removed. + */ + RESOURCE_REMOVED + } + + /** + * Create a resource event. + * + * @param type type of resource event + * @param subject subject of resource event + */ + public ResourceEvent(Type type, ResourcePath subject) { + super(checkNotNull(type), checkNotNull(subject)); + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceListener.java new file mode 100644 index 00000000..3f871900 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceListener.java @@ -0,0 +1,26 @@ +/* + * 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.newresource; + +import com.google.common.annotations.Beta; +import org.onosproject.event.EventListener; + +/** + * Entity capable of receiving resource related events. + */ +@Beta +public interface ResourceListener extends EventListener<ResourceEvent> { +} 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/main/java/org/onosproject/net/newresource/ResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java index ad684c8c..966de500 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 @@ -17,6 +17,7 @@ package org.onosproject.net.newresource; import com.google.common.annotations.Beta; import com.google.common.collect.ImmutableList; +import org.onosproject.event.ListenerService; import java.util.Arrays; import java.util.Collection; @@ -29,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull; * Service for allocating/releasing resource(s) and retrieving allocation(s) and availability. */ @Beta -public interface ResourceService { +public interface ResourceService extends ListenerService<ResourceEvent, ResourceListener> { /** * Allocates the specified resource to the specified user. * 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 2cab9d4b..7c67430e 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 @@ -16,6 +16,7 @@ package org.onosproject.net.newresource; import com.google.common.annotations.Beta; +import org.onosproject.store.Store; import java.util.Collection; import java.util.List; @@ -25,7 +26,7 @@ import java.util.Optional; * Service for storing resource and consumer information. */ @Beta -public interface ResourceStore { +public interface ResourceStore extends Store<ResourceEvent, ResourceStoreDelegate> { /** * Registers the resources in transactional way. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStoreDelegate.java new file mode 100644 index 00000000..a0b9bb25 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStoreDelegate.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.net.newresource; + +import org.onosproject.store.StoreDelegate; + +/** + * Resource store delegate abstraction. + */ +public interface ResourceStoreDelegate extends StoreDelegate<ResourceEvent> { +} 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 0bfb3795..d3bd2d7b 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 @@ -23,7 +23,10 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Representation of bandwidth resource in bps. + * + * @deprecated in Emu Release */ +@Deprecated public final class BandwidthResource implements LinkResource { private final Bandwidth bandwidth; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java index 74f6e102..5f36d5f8 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceAllocation.java @@ -23,7 +23,10 @@ import java.util.Objects; /** * Representation of allocated bandwidth resource. + * + * @deprecated in Emu Release */ +@Deprecated public class BandwidthResourceAllocation implements ResourceAllocation { private final BandwidthResource bandwidth; @@ -53,7 +56,7 @@ public class BandwidthResourceAllocation implements ResourceAllocation { @Override public int hashCode() { - return Objects.hash(bandwidth); + return bandwidth.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java index e07309cb..ff26e81e 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResourceRequest.java @@ -23,7 +23,10 @@ import org.onosproject.net.resource.ResourceType; /** * Representation of a request for bandwidth resource. + * + * @deprecated in Emu Release */ +@Deprecated public class BandwidthResourceRequest implements ResourceRequest { private final BandwidthResource bandwidth; @@ -53,7 +56,7 @@ public class BandwidthResourceRequest implements ResourceRequest { @Override public int hashCode() { - return Objects.hash(bandwidth); + return bandwidth.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java index 379bf71e..2fa4fa6b 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceAllocations.java @@ -36,7 +36,10 @@ import java.util.Set; /** * Implementation of {@link LinkResourceAllocations}. + * + * @deprecated in Emu Release */ +@Deprecated public class DefaultLinkResourceAllocations implements LinkResourceAllocations { private final LinkResourceRequest request; // TODO: probably should be using LinkKey instead 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 f8e143a4..b57465f2 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 @@ -39,7 +39,10 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Implementation of {@link LinkResourceRequest}. + * + * @deprecated in Emu Release */ +@Deprecated public final class DefaultLinkResourceRequest implements LinkResourceRequest { private final IntentId intentId; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java index 3733e467..06582497 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResource.java @@ -23,7 +23,10 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Representation of lambda resource. + * + * @deprecated in Emu Release */ +@Deprecated public final class LambdaResource implements LinkResource { private final IndexedLambda lambda; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java index 545f025f..930a6b27 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceAllocation.java @@ -23,7 +23,10 @@ import java.util.Objects; /** * Representation of allocated lambda resource. + * + * @deprecated in Emu Release */ +@Deprecated public class LambdaResourceAllocation implements ResourceAllocation { private final LambdaResource lambda; @@ -53,7 +56,7 @@ public class LambdaResourceAllocation implements ResourceAllocation { @Override public int hashCode() { - return Objects.hash(lambda); + return Objects.hashCode(lambda); } @Override 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 d264d5e5..24d3d78d 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 @@ -24,7 +24,10 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Representation of a request for lambda resource. + * + * @deprecated in Emu Release */ +@Deprecated public class LambdaResourceRequest implements ResourceRequest { private final LambdaResource lambda; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java index ec06611e..b06f16bf 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResource.java @@ -17,6 +17,9 @@ package org.onosproject.net.resource.link; /** * Abstraction of link resource. + * + * @deprecated in Emu Release */ +@Deprecated public interface LinkResource { } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java index 7828867c..d0211e26 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceAllocations.java @@ -25,7 +25,10 @@ import org.onosproject.net.resource.ResourceRequest; /** * Representation of allocated link resources. + * + * @deprecated */ +@Deprecated public interface LinkResourceAllocations extends ResourceAllocation { /** diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java index 3edb386a..a3702923 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceEvent.java @@ -23,7 +23,10 @@ import com.google.common.collect.ImmutableList; /** * Describes an event related to a Link Resource. + * + * @deprecated in Emu Release */ +@Deprecated public final class LinkResourceEvent extends AbstractEvent<LinkResourceEvent.Type, Collection<LinkResourceAllocations>> { diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java index 599dd4fb..bbb02e2f 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceListener.java @@ -19,6 +19,9 @@ import org.onosproject.event.EventListener; /** * Entity for receiving link resource events. + * + * @deprecated in Emu Release */ +@Deprecated public interface LinkResourceListener extends EventListener<LinkResourceEvent> { } 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 37622e79..9774e8e7 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 @@ -27,7 +27,10 @@ import org.onosproject.net.resource.ResourceRequest; /** * Representation of a request for link resource. + * + * @deprecated in Emu Release */ +@Deprecated public interface LinkResourceRequest extends ResourceRequest { /** diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java index e6674dbd..e8a295c2 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStore.java @@ -23,7 +23,10 @@ import org.onosproject.net.resource.ResourceAllocation; /** * Manages link resources. + * + * @deprecated in Emu Release. */ +@Deprecated public interface LinkResourceStore { /** * Returns free resources for given link. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java index 6c051d6a..dbfb3b04 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceStoreDelegate.java @@ -19,6 +19,9 @@ import org.onosproject.store.StoreDelegate; /** * Link resource store delegate abstraction. + * + * @deprecated in Emu Release */ +@Deprecated public interface LinkResourceStoreDelegate extends StoreDelegate<LinkResourceEvent> { } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java index dc005227..46450427 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResources.java @@ -19,7 +19,10 @@ import java.util.Set; /** * Abstraction of a resources of a link. + * + * @deprecated in Emu Release */ +@Deprecated public interface LinkResources { /** @@ -31,7 +34,10 @@ public interface LinkResources { /** * Builder of {@link LinkResources}. + * + * @deprecated in Emu Release */ + @Deprecated interface Builder { /** diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java index 89c87760..5138d02c 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabel.java @@ -20,7 +20,10 @@ import java.util.Objects; /** * Representation of MPLS label resource. + * + * @deprecated in Emu Release */ +@Deprecated public final class MplsLabel implements LinkResource { private final org.onlab.packet.MplsLabel mplsLabel; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java index 10911539..7441bee9 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceAllocation.java @@ -24,7 +24,10 @@ import java.util.Objects; /** * Representation of allocated MPLS label resource. + * + * @deprecated in Emu Release */ +@Deprecated public class MplsLabelResourceAllocation implements ResourceAllocation { private final MplsLabel mplsLabel; @@ -54,7 +57,7 @@ public class MplsLabelResourceAllocation implements ResourceAllocation { @Override public int hashCode() { - return Objects.hash(mplsLabel); + return Objects.hashCode(mplsLabel); } @Override 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 01a048b7..5b9c4a0a 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 @@ -24,7 +24,10 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Representation of a request for lambda resource. + * + * @deprecated in Emu Release */ +@Deprecated public class MplsLabelResourceRequest implements ResourceRequest { private final MplsLabel mplsLabel; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java index b10e4ba4..f374d778 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/package-info.java @@ -17,5 +17,11 @@ /** * Services for reserving links and their capacity as network resources, * e.g. bandwidth, lambdas. + * <p> + * Note: Classes under the package will be remove. + * Developers should not use the classes. + * This package is marked as deprecated in Emu Release. + * </p> */ +@Deprecated package org.onosproject.net.resource.link; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java index e676fc87..a05dfda1 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/package-info.java @@ -16,5 +16,9 @@ /** * Abstractions for reserving network resources. + * <p> + * Note: Classes under the package will be removed. + * Developers should not use the classes. + * </p> */ package org.onosproject.net.resource; diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java index 676f0068..1e6780fa 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/ClusterId.java @@ -53,7 +53,7 @@ public final class ClusterId { @Override public int hashCode() { - return Objects.hash(id); + return id; } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java index dacb5fd8..99d700e1 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyEdge.java @@ -20,6 +20,7 @@ import org.onosproject.net.Link; import java.util.Objects; import static com.google.common.base.MoreObjects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; /** * Implementation of the topology edge backed by a link. @@ -40,7 +41,7 @@ public class DefaultTopologyEdge implements TopologyEdge { public DefaultTopologyEdge(TopologyVertex src, TopologyVertex dst, Link link) { this.src = src; this.dst = dst; - this.link = link; + this.link = checkNotNull(link); } @Override @@ -60,7 +61,7 @@ public class DefaultTopologyEdge implements TopologyEdge { @Override public int hashCode() { - return Objects.hash(link); + return link.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java index 07a09cbd..4782bc95 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/topology/DefaultTopologyVertex.java @@ -42,7 +42,7 @@ public class DefaultTopologyVertex implements TopologyVertex { @Override public int hashCode() { - return Objects.hash(deviceId); + return deviceId.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java index 0cc7b453..4be7ede7 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/WallClockTimestamp.java @@ -52,7 +52,7 @@ public class WallClockTimestamp implements Timestamp { } @Override public int hashCode() { - return Objects.hash(unixTimestamp); + return Long.hashCode(unixTimestamp); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java index 2b8b7fa2..c8671159 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiView.java @@ -138,7 +138,7 @@ public class UiView { @Override public int hashCode() { - return Objects.hash(id); + return id.hashCode(); } @Override diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java index a165be33..c75eccf9 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/PropertyPanel.java @@ -18,7 +18,7 @@ package org.onosproject.ui.topo; import com.google.common.collect.Sets; -import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -28,7 +28,7 @@ import java.util.Set; */ public class PropertyPanel { - private static final DecimalFormat DF0 = new DecimalFormat("#,###"); + private static final NumberFormat NF = NumberFormat.getInstance(); private String title; private String typeId; @@ -49,6 +49,24 @@ public class PropertyPanel { } /** + * Returns a number formatter to use for formatting integer and long + * property values. + * <p> + * This default implementation uses a formatter for the default + * locale. For example: + * <pre> + * Locale.ENGLISH : 1000 -> "1,000" + * Locale.FRENCH : 1000 -> "1 000" + * Locale.GERMAN : 1000 -> "1.000" + * </pre> + * + * @return the number formatter + */ + protected NumberFormat formatter() { + return NF; + } + + /** * Adds an ID field to the panel data, to be included in * the returned JSON data to the client. * @@ -80,7 +98,7 @@ public class PropertyPanel { * @return self, for chaining */ public PropertyPanel addProp(String key, int value) { - properties.add(new Prop(key, DF0.format(value))); + properties.add(new Prop(key, formatter().format(value))); return this; } @@ -92,7 +110,7 @@ public class PropertyPanel { * @return self, for chaining */ public PropertyPanel addProp(String key, long value) { - properties.add(new Prop(key, DF0.format(value))); + properties.add(new Prop(key, formatter().format(value))); return this; } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java index d31cc268..34c593c4 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java @@ -33,7 +33,7 @@ public class ApplicationEventTest extends AbstractEventTest { private Application createApp() { return new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, - PERMS, Optional.of(FURL), FEATURES); + PERMS, Optional.of(FURL), FEATURES, APPS); } @Test diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java b/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java index 479cc59a..96324a91 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java @@ -51,6 +51,10 @@ public class ApplicationServiceAdapter implements ApplicationService { } @Override + public void registerDeactivateHook(ApplicationId appId, Runnable hook) { + } + + @Override public void addListener(ApplicationListener listener) { } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java index d40d3fea..0e93c1fe 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java @@ -46,12 +46,13 @@ public class DefaultApplicationDescriptionTest { new Permission(AppPermission.class.getName(), "FLOWRULE_READ")); public static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features"); public static final List<String> FEATURES = ImmutableList.of("foo", "bar"); + public static final List<String> APPS = ImmutableList.of("fifi"); @Test public void basics() { ApplicationDescription app = new DefaultApplicationDescription(APP_NAME, VER, DESC, ORIGIN, - ROLE, PERMS, FURL, FEATURES); + ROLE, PERMS, FURL, FEATURES, APPS); assertEquals("incorrect id", APP_NAME, app.name()); assertEquals("incorrect version", VER, app.version()); assertEquals("incorrect description", DESC, app.description()); @@ -60,6 +61,7 @@ public class DefaultApplicationDescriptionTest { assertEquals("incorrect permissions", PERMS, app.permissions()); assertEquals("incorrect features repo", FURL, app.featuresRepo().get()); assertEquals("incorrect features", FEATURES, app.features()); + assertEquals("incorrect apps", APPS, app.requiredApps()); assertTrue("incorrect toString", app.toString().contains(APP_NAME)); } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/core/CoreServiceAdapter.java b/framework/src/onos/core/api/src/test/java/org/onosproject/core/CoreServiceAdapter.java index 0f6abd68..6d45e8c5 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/core/CoreServiceAdapter.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/core/CoreServiceAdapter.java @@ -43,7 +43,12 @@ public class CoreServiceAdapter implements CoreService { } @Override - public ApplicationId registerApplication(String identifier) { + public ApplicationId registerApplication(String name) { + return null; + } + + @Override + public ApplicationId registerApplication(String name, Runnable preDeactivate) { return null; } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java index cbedb79c..77b3812b 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java @@ -34,7 +34,7 @@ public class DefaultApplicationTest { @Test public void basics() { Application app = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, - PERMS, Optional.of(FURL), FEATURES); + PERMS, Optional.of(FURL), FEATURES, APPS); assertEquals("incorrect id", APP_ID, app.id()); assertEquals("incorrect version", VER, app.version()); assertEquals("incorrect description", DESC, app.description()); @@ -43,19 +43,20 @@ public class DefaultApplicationTest { assertEquals("incorrect permissions", PERMS, app.permissions()); assertEquals("incorrect features repo", FURL, app.featuresRepo().get()); assertEquals("incorrect features", FEATURES, app.features()); + assertEquals("incorrect apps", APPS, app.requiredApps()); assertTrue("incorrect toString", app.toString().contains(APP_NAME)); } @Test public void testEquality() { Application a1 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, - PERMS, Optional.of(FURL), FEATURES); + PERMS, Optional.of(FURL), FEATURES, APPS); Application a2 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, - PERMS, Optional.of(FURL), FEATURES); + PERMS, Optional.of(FURL), FEATURES, APPS); Application a3 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, - PERMS, Optional.empty(), FEATURES); + PERMS, Optional.empty(), FEATURES, APPS); Application a4 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN + "asd", ROLE, - PERMS, Optional.of(FURL), FEATURES); + PERMS, Optional.of(FURL), FEATURES, APPS); new EqualsTester().addEqualityGroup(a1, a2) .addEqualityGroup(a3).addEqualityGroup(a4).testEquals(); } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/PortNumberTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/PortNumberTest.java index 6f7b2c2d..de153dc2 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/PortNumberTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/PortNumberTest.java @@ -15,12 +15,17 @@ */ package org.onosproject.net; +import com.google.common.collect.ImmutableList; import com.google.common.testing.EqualsTester; import org.junit.Test; +import org.onosproject.net.PortNumber.Logical; +import static java.util.stream.Collectors.toList; import static org.junit.Assert.assertEquals; import static org.onosproject.net.PortNumber.portNumber; +import java.util.List; + /** * Test of the port number. */ @@ -39,5 +44,37 @@ public class PortNumberTest { assertEquals("incorrect long value", 12345, portNumber(12345).toLong()); } + @Test + public void decimalPortNumberIsReconstructableFromString() { + List<PortNumber> ps = ImmutableList.<PortNumber>builder() + .add(portNumber(0)) + .add(portNumber(1)) + .add(portNumber(6653)) + .add(portNumber(PortNumber.MAX_NUMBER)) + .build(); + ps.forEach(p -> assertEquals(p, PortNumber.fromString(p.toString()))); + } + + @Test + public void logicalPortNumberIsReconstructableFromString() { + List<PortNumber> ps = ImmutableList.copyOf(Logical.values()) + .stream().map(Logical::instance).collect(toList()); + + ps.forEach(p -> assertEquals(p, PortNumber.fromString(p.toString()))); + + PortNumber unknown = portNumber(-42); + assertEquals(unknown, PortNumber.fromString(unknown.toString())); + } + + @Test + public void namedPortNumberIsReconstructableFromString() { + List<PortNumber> ps = ImmutableList.<PortNumber>builder() + .add(portNumber(0, "Zero")) + .add(portNumber(1, "[ONE]")) + .add(portNumber(6653, "OpenFlow (1.3+)")) + .add(portNumber(PortNumber.MAX_NUMBER, "(大)")) + .build(); + ps.forEach(p -> assertEquals(p, PortNumber.fromString(p.toString()))); + } } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/device/DefaultDeviceDescriptionTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/device/DefaultDeviceDescriptionTest.java index 3dcdc22d..c00a6de0 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/device/DefaultDeviceDescriptionTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/device/DefaultDeviceDescriptionTest.java @@ -41,7 +41,7 @@ public class DefaultDeviceDescriptionTest { public void basics() { DeviceDescription device = new DefaultDeviceDescription(DURI, SWITCH, MFR, HW, SW, SN, CID); - assertEquals("incorrect uri", DURI, device.deviceURI()); + assertEquals("incorrect uri", DURI, device.deviceUri()); assertEquals("incorrect type", SWITCH, device.type()); assertEquals("incorrect manufacturer", MFR, device.manufacturer()); assertEquals("incorrect hw", HW, device.hwVersion()); diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/driver/XmlDriverLoaderTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/driver/XmlDriverLoaderTest.java index f54e7411..15abc2bf 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/driver/XmlDriverLoaderTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/driver/XmlDriverLoaderTest.java @@ -57,7 +57,7 @@ public class XmlDriverLoaderTest { } @Test(expected = IOException.class) - public void badXML() throws IOException { + public void badXml() throws IOException { XmlDriverLoader loader = new XmlDriverLoader(getClass().getClassLoader()); loader.loadDrivers(getClass().getResourceAsStream("drivers.bad.xml"), null); } @@ -77,4 +77,4 @@ public class XmlDriverLoaderTest { driver.createBehaviour(new DefaultDriverData(driver, DEVICE_ID), TestBehaviour.class); } -}
\ No newline at end of file +} diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/ConnectivityIntentTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/ConnectivityIntentTest.java index e03ed850..c510b60a 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/ConnectivityIntentTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/ConnectivityIntentTest.java @@ -33,6 +33,7 @@ import org.onosproject.net.flow.TrafficTreatment; public abstract class ConnectivityIntentTest extends IntentTest { public static final ApplicationId APPID = new TestApplicationId("foo"); + public static final Key KEY = Key.of(1L, APPID); public static final IntentId IID = new IntentId(123); public static final TrafficSelector MATCH = DefaultTrafficSelector.emptySelector(); diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java index d42e22fa..14201472 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java @@ -192,14 +192,17 @@ public class IntentTestsMocks { new MplsLabelResourceAllocation(MplsLabel.valueOf(10))); } + @Override public IntentId intentId() { return null; } + @Override public Collection<Link> links() { return null; } + @Override public Set<ResourceRequest> resources() { return null; } @@ -408,7 +411,7 @@ public class IntentTestsMocks { @Override public int hashCode() { - return Objects.hash(priority); + return priority; } @Override diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsIntentTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsIntentTest.java index 196d6ad4..7fbdf232 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsIntentTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsIntentTest.java @@ -112,6 +112,5 @@ public class MplsIntentTest extends AbstractIntentTest { assertThat(intent1.selector(), equalTo(intent2.selector())); assertThat(intent1.treatment(), equalTo(intent2.treatment())); assertThat(intent1.priority(), is(PRIORITY)); - } } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsPathIntentTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsPathIntentTest.java index 551f19eb..64528cb9 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsPathIntentTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/MplsPathIntentTest.java @@ -47,6 +47,7 @@ public class MplsPathIntentTest extends AbstractIntentTest { Optional<MplsLabel> label2; TrafficSelector selector; TrafficTreatment treatment; + static final Key KEY1 = Key.of(5L, APP_ID); @Before public void mplsPathIntentTestSetUp() { @@ -58,6 +59,7 @@ public class MplsPathIntentTest extends AbstractIntentTest { label2 = Optional.of(MplsLabel.mplsLabel(2)); intent1 = MplsPathIntent.builder() .appId(APP_ID) + .key(KEY1) .ingressLabel(label1) .egressLabel(label2) .path(defaultPath) @@ -105,6 +107,7 @@ public class MplsPathIntentTest extends AbstractIntentTest { assertThat(intent1.treatment(), equalTo(intent2.treatment())); assertThat(intent1.priority(), is(PRIORITY)); assertThat(intent1.path(), is(defaultPath)); + assertThat(intent1.key(), equalTo(KEY1)); } } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/PathIntentTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/PathIntentTest.java index dfbc1846..9e675347 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/PathIntentTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/PathIntentTest.java @@ -62,12 +62,14 @@ public class PathIntentTest extends ConnectivityIntentTest { assertEquals("incorrect match", MATCH, intent.selector()); assertEquals("incorrect action", NOP, intent.treatment()); assertEquals("incorrect path", PATH1, intent.path()); + assertEquals("incorrect key", KEY, intent.key()); } @Override protected PathIntent createOne() { return PathIntent.builder() .appId(APPID) + .key(KEY) .selector(MATCH) .treatment(NOP) .path(PATH1) 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/api/src/test/java/org/onosproject/ui/table/cell/DefaultCellComparatorTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/table/cell/DefaultCellComparatorTest.java index d77c1b2b..b870d483 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/ui/table/cell/DefaultCellComparatorTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/table/cell/DefaultCellComparatorTest.java @@ -115,19 +115,19 @@ public class DefaultCellComparatorTest { } @Test - public void swEpisodeII() { + public void swEpisodeIi() { assertTrue("r2d2 c3po", cmp.compare(SmallStarWars.R2D2, SmallStarWars.C3PO) > 0); } @Test - public void swEpisodeIII() { + public void swEpisodeIii() { assertTrue("luke c3po", cmp.compare(SmallStarWars.LUKE, SmallStarWars.C3PO) > 0); } @Test - public void swEpisodeIV() { + public void swEpisodeIv() { assertTrue("c3po luke", cmp.compare(SmallStarWars.C3PO, SmallStarWars.LUKE) < 0); } @@ -139,7 +139,7 @@ public class DefaultCellComparatorTest { } @Test - public void swEpisodeVI() { + public void swEpisodeVi() { assertTrue("r2d2 luke", cmp.compare(SmallStarWars.R2D2, SmallStarWars.LUKE) < 0); } diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/PropertyPanelTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/PropertyPanelTest.java index 7e6cc227..b6d32bed 100644 --- a/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/PropertyPanelTest.java +++ b/framework/src/onos/core/api/src/test/java/org/onosproject/ui/topo/PropertyPanelTest.java @@ -20,17 +20,38 @@ import org.junit.BeforeClass; import org.junit.Test; import org.onosproject.ui.topo.PropertyPanel.Prop; +import java.text.NumberFormat; import java.util.HashMap; import java.util.Iterator; +import java.util.Locale; import java.util.Map; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; /** * Unit tests for {@link PropertyPanel}. */ public class PropertyPanelTest { + // Modified property panel subclass to use ENGLISH locale formatter so + // we know formatted numbers will use comma for the thousand separator. + private static final class EnglishPropertyPanel extends PropertyPanel { + private static final NumberFormat ENGLISH_FORMATTER = + NumberFormat.getInstance(Locale.ENGLISH); + + public EnglishPropertyPanel(String title, String typeId) { + super(title, typeId); + } + + @Override + protected NumberFormat formatter() { + return ENGLISH_FORMATTER; + } + } + private static final String TITLE_ORIG = "Original Title"; private static final String TYPE_ORIG = "Original type ID"; private static final String TITLE_NEW = "New Title"; @@ -42,6 +63,7 @@ public class PropertyPanelTest { private static final String KEY_C = "C"; private static final String SEP = "-"; private static final String KEY_Z = "Z"; + private static final String VALUE_A = "Hay"; private static final String VALUE_B = "Bee"; private static final String VALUE_C = "Sea"; @@ -76,7 +98,7 @@ public class PropertyPanelTest { @Test public void basic() { - pp = new PropertyPanel(TITLE_ORIG, TYPE_ORIG); + pp = new EnglishPropertyPanel(TITLE_ORIG, TYPE_ORIG); assertEquals("wrong title", TITLE_ORIG, pp.title()); assertEquals("wrong type", TYPE_ORIG, pp.typeId()); assertNull("id?", pp.id()); @@ -134,8 +156,8 @@ public class PropertyPanelTest { public void props() { basic(); pp.addProp(KEY_A, VALUE_A) - .addProp(KEY_B, VALUE_B) - .addProp(KEY_C, VALUE_C); + .addProp(KEY_B, VALUE_B) + .addProp(KEY_C, VALUE_C); assertEquals("bad props", 3, pp.properties().size()); validateProps(KEY_A, KEY_B, KEY_C); } @@ -144,7 +166,7 @@ public class PropertyPanelTest { public void separator() { props(); pp.addSeparator() - .addProp(KEY_Z, VALUE_Z); + .addProp(KEY_Z, VALUE_Z); assertEquals("bad props", 5, pp.properties().size()); validateProps(KEY_A, KEY_B, KEY_C, SEP, KEY_Z); @@ -170,8 +192,8 @@ public class PropertyPanelTest { public void intValues() { basic(); pp.addProp(KEY_A, 200) - .addProp(KEY_B, 2000) - .addProp(KEY_C, 1234567); + .addProp(KEY_B, 2000) + .addProp(KEY_C, 1234567); validateProp(KEY_A, "200"); validateProp(KEY_B, "2,000"); @@ -182,9 +204,9 @@ public class PropertyPanelTest { public void longValues() { basic(); pp.addProp(KEY_A, 200L) - .addProp(KEY_B, 2000L) - .addProp(KEY_C, 1234567L) - .addProp(KEY_Z, Long.MAX_VALUE); + .addProp(KEY_B, 2000L) + .addProp(KEY_C, 1234567L) + .addProp(KEY_Z, Long.MAX_VALUE); validateProp(KEY_A, "200"); validateProp(KEY_B, "2,000"); @@ -196,7 +218,7 @@ public class PropertyPanelTest { public void objectValue() { basic(); pp.addProp(KEY_A, new FooClass("a")) - .addProp(KEY_B, new FooClass("bxyyzy"), "[xz]"); + .addProp(KEY_B, new FooClass("bxyyzy"), "[xz]"); validateProp(KEY_A, ">a<"); validateProp(KEY_B, ">byyy<"); diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java index b2cab094..a09c0bdb 100644 --- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java @@ -32,18 +32,18 @@ public final class ApplicationCodec extends JsonCodec<Application> { public ObjectNode encode(Application app, CodecContext context) { checkNotNull(app, "Application cannot be null"); ApplicationService service = context.getService(ApplicationService.class); - ObjectNode result = context.mapper().createObjectNode() + return context.mapper().createObjectNode() .put("name", app.id().name()) .put("id", app.id().id()) .put("version", app.version().toString()) .put("description", app.description()) .put("origin", app.origin()) - .put("permissions", app.permissions().toString()) + .put("permissions", app.permissions().toString()) // FIXME: change to an array .put("featuresRepo", app.featuresRepo().isPresent() ? app.featuresRepo().get().toString() : "") - .put("features", app.features().toString()) + .put("features", app.features().toString()) // FIXME: change to an array + .put("requiredApps", app.requiredApps().toString()) // FIXME: change to an array .put("state", service.getState(app.id()).toString()); - return result; } } diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java b/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java index 3c5c540d..84cde424 100644 --- a/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/common/DefaultTopology.java @@ -26,10 +26,10 @@ import org.onlab.graph.DijkstraGraphSearch; import org.onlab.graph.DisjointPathPair; import org.onlab.graph.GraphPathSearch; import org.onlab.graph.GraphPathSearch.Result; -import org.onlab.graph.SRLGGraphSearch; +import org.onlab.graph.SrlgGraphSearch; import org.onlab.graph.SuurballeGraphSearch; import org.onlab.graph.TarjanGraphSearch; -import org.onlab.graph.TarjanGraphSearch.SCCResult; +import org.onlab.graph.TarjanGraphSearch.SccResult; import org.onosproject.net.AbstractModel; import org.onosproject.net.ConnectPoint; import org.onosproject.net.DefaultDisjointPath; @@ -83,7 +83,7 @@ public class DefaultTopology extends AbstractModel implements Topology { private final TopologyGraph graph; private final LinkWeight weight; - private final Supplier<SCCResult<TopologyVertex, TopologyEdge>> clusterResults; + private final Supplier<SccResult<TopologyVertex, TopologyEdge>> clusterResults; private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters; private final Supplier<ImmutableSet<ConnectPoint>> infrastructurePoints; private final Supplier<ImmutableSetMultimap<ClusterId, ConnectPoint>> broadcastSets; @@ -385,7 +385,7 @@ public class DefaultTopology extends AbstractModel implements Topology { return ImmutableSet.of(); } - SRLGGraphSearch<TopologyVertex, TopologyEdge> srlg = new SRLGGraphSearch<>(riskProfile); + SrlgGraphSearch<TopologyVertex, TopologyEdge> srlg = new SrlgGraphSearch<>(riskProfile); GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = srlg.search(graph, srcV, dstV, weight, ALL_PATHS); ImmutableSet.Builder<DisjointPath> builder = ImmutableSet.builder(); @@ -455,14 +455,14 @@ public class DefaultTopology extends AbstractModel implements Topology { // Searches for SCC clusters in the network topology graph using Tarjan // algorithm. - private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() { + private SccResult<TopologyVertex, TopologyEdge> searchForClusters() { return TARJAN.search(graph, new NoIndirectLinksWeight()); } // Builds the topology clusters and returns the id-cluster bindings. private ImmutableMap<ClusterId, TopologyCluster> buildTopologyClusters() { ImmutableMap.Builder<ClusterId, TopologyCluster> clusterBuilder = ImmutableMap.builder(); - SCCResult<TopologyVertex, TopologyEdge> results = clusterResults.get(); + SccResult<TopologyVertex, TopologyEdge> results = clusterResults.get(); // Extract both vertexes and edges from the results; the lists form // pairs along the same index. diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java b/framework/src/onos/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java index 54f0fb89..37cdbdfc 100644 --- a/framework/src/onos/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java +++ b/framework/src/onos/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java @@ -17,6 +17,7 @@ package org.onosproject.common.app; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.common.io.ByteStreams; import com.google.common.io.Files; import org.apache.commons.configuration.ConfigurationException; @@ -33,7 +34,6 @@ import org.onosproject.core.Version; import org.onosproject.security.AppPermission; import org.onosproject.security.Permission; import org.onosproject.store.AbstractStore; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +46,6 @@ import java.io.InputStream; import java.net.URI; import java.nio.charset.Charset; import java.nio.file.NoSuchFileException; -import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Set; @@ -79,6 +78,7 @@ public class ApplicationArchive private static final String VERSION = "[@version]"; private static final String FEATURES_REPO = "[@featuresRepo]"; private static final String FEATURES = "[@features]"; + private static final String APPS = "[@apps]"; private static final String DESCRIPTION = "description"; private static final String ROLE = "security.role"; @@ -291,8 +291,13 @@ public class ApplicationArchive URI featuresRepo = featRepo != null ? URI.create(featRepo) : null; List<String> features = ImmutableList.copyOf(cfg.getString(FEATURES).split(",")); + String apps = cfg.getString(APPS, ""); + List<String> requiredApps = apps.isEmpty() ? + ImmutableList.of() : ImmutableList.copyOf(apps.split(",")); + return new DefaultApplicationDescription(name, version, desc, origin, role, - perms, featuresRepo, features); + perms, featuresRepo, features, + requiredApps); } // Expands the specified ZIP stream into app-specific directory. @@ -390,7 +395,7 @@ public class ApplicationArchive // Returns the set of Permissions specified in the app.xml file private ImmutableSet<Permission> getPermissions(XMLConfiguration cfg) { - List<Permission> permissionList = new ArrayList(); + List<Permission> permissionList = Lists.newArrayList(); for (Object o : cfg.getList(APP_PERMISSIONS)) { String name = (String) o; diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java index 7cbce4d1..2f933966 100644 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java @@ -217,7 +217,7 @@ public class IntentCodecTest extends AbstractIntentTest { * @throws IOException if processing the resource fails */ private Intent getIntent(String resourceName, JsonCodec intentCodec) throws IOException { - InputStream jsonStream = FlowRuleCodecTest.class + InputStream jsonStream = IntentCodecTest.class .getResourceAsStream(resourceName); JsonNode json = context.mapper().readTree(jsonStream); assertThat(json, notNullValue()); diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java index ea9a773e..d9f5285c 100644 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java @@ -75,7 +75,8 @@ public class SimpleApplicationStore extends ApplicationArchive implements Applic new DefaultApplication(appId, appDesc.version(), appDesc.description(), appDesc.origin(), appDesc.role(), appDesc.permissions(), - appDesc.featuresRepo(), appDesc.features()); + appDesc.featuresRepo(), appDesc.features(), + appDesc.requiredApps()); apps.put(appId, app); states.put(appId, isActive(name) ? INSTALLED : ACTIVE); // load app permissions @@ -117,7 +118,8 @@ public class SimpleApplicationStore extends ApplicationArchive implements Applic DefaultApplication app = new DefaultApplication(appId, appDesc.version(), appDesc.description(), appDesc.origin(), appDesc.role(), appDesc.permissions(), - appDesc.featuresRepo(), appDesc.features()); + appDesc.featuresRepo(), appDesc.features(), + appDesc.requiredApps()); apps.put(appId, app); states.put(appId, INSTALLED); delegate.notify(new ApplicationEvent(APP_INSTALLED, app)); diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java index 72fc1b05..11a12040 100644 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java @@ -532,7 +532,7 @@ public class SimpleDeviceStore checkArgument(!providerDescs.isEmpty(), "No Device descriptions supplied"); - ProviderId primary = pickPrimaryPID(providerDescs); + ProviderId primary = pickPrimaryPid(providerDescs); DeviceDescriptions desc = providerDescs.get(primary); @@ -575,7 +575,7 @@ public class SimpleDeviceStore private Port composePort(Device device, PortNumber number, Map<ProviderId, DeviceDescriptions> descsMap) { - ProviderId primary = pickPrimaryPID(descsMap); + ProviderId primary = pickPrimaryPid(descsMap); DeviceDescriptions primDescs = descsMap.get(primary); // if no primary, assume not enabled // TODO: revisit this default port enabled/disabled behavior @@ -613,7 +613,7 @@ public class SimpleDeviceStore /** * @return primary ProviderID, or randomly chosen one if none exists */ - private ProviderId pickPrimaryPID(Map<ProviderId, DeviceDescriptions> descsMap) { + private ProviderId pickPrimaryPid(Map<ProviderId, DeviceDescriptions> descsMap) { ProviderId fallBackPrimary = null; for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) { if (!e.getKey().isAncillary()) { diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java index 72ec98ca..a56daab1 100644 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleHostStore.java @@ -88,10 +88,14 @@ public class SimpleHostStore boolean replaceIps) { //TODO We need a way to detect conflicting changes and abort update. StoredHost host = hosts.get(hostId); + HostEvent hostEvent; if (host == null) { - return createHost(providerId, hostId, hostDescription); + hostEvent = createHost(providerId, hostId, hostDescription); + } else { + hostEvent = updateHost(providerId, host, hostDescription, replaceIps); } - return updateHost(providerId, host, hostDescription, replaceIps); + notifyDelegate(hostEvent); + return hostEvent; } // creates a new host and sends HOST_ADDED @@ -153,7 +157,9 @@ public class SimpleHostStore Host host = hosts.remove(hostId); if (host != null) { locations.remove((host.location()), host); - return new HostEvent(HOST_REMOVED, host); + HostEvent hostEvent = new HostEvent(HOST_REMOVED, host); + notifyDelegate(hostEvent); + return hostEvent; } return null; } diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleLinkResourceStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleLinkResourceStore.java index 58b446cf..22df937b 100644 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleLinkResourceStore.java +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleLinkResourceStore.java @@ -52,7 +52,10 @@ import static org.slf4j.LoggerFactory.getLogger; /** * Manages link resources using trivial in-memory structures implementation. + * + * @deprecated in Emu Release */ +@Deprecated @Component(immediate = true) @Service public class SimpleLinkResourceStore implements LinkResourceStore { diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SystemClockTimestamp.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SystemClockTimestamp.java index 2ee41945..500a09c7 100644 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SystemClockTimestamp.java +++ b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SystemClockTimestamp.java @@ -51,7 +51,7 @@ public class SystemClockTimestamp implements Timestamp { } @Override public int hashCode() { - return Objects.hash(nanoTimestamp); + return Long.hashCode(nanoTimestamp); } @Override diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java index 161659f9..d09eb1f1 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java @@ -15,6 +15,7 @@ */ package org.onosproject.app.impl; +import com.google.common.collect.Maps; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -30,20 +31,21 @@ import org.onosproject.app.ApplicationService; import org.onosproject.app.ApplicationState; import org.onosproject.app.ApplicationStore; import org.onosproject.app.ApplicationStoreDelegate; -import org.onosproject.event.AbstractListenerManager; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; +import org.onosproject.event.AbstractListenerManager; import org.onosproject.security.Permission; import org.onosproject.security.SecurityUtil; import org.slf4j.Logger; import java.io.InputStream; +import java.util.Map; import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; import static org.onosproject.app.ApplicationEvent.Type.*; -import static org.onosproject.security.AppPermission.Type.*; import static org.onosproject.security.AppGuard.checkPermission; +import static org.onosproject.security.AppPermission.Type.APP_READ; import static org.slf4j.LoggerFactory.getLogger; /** @@ -69,6 +71,9 @@ public class ApplicationManager private boolean initializing; + // Application supplied hooks for pre-activation processing. + private final Map<String, Runnable> deactivateHooks = Maps.newConcurrentMap(); + @Activate public void activate() { eventDispatcher.addSink(ApplicationEvent.class, listenerRegistry); @@ -122,6 +127,14 @@ public class ApplicationManager } @Override + public void registerDeactivateHook(ApplicationId appId, Runnable hook) { + checkPermission(APP_READ); + checkNotNull(appId, APP_ID_NULL); + checkNotNull(hook, "Hook cannot be null"); + deactivateHooks.put(appId.name(), hook); + } + + @Override public Application install(InputStream appDescStream) { checkNotNull(appDescStream, "Application archive stream cannot be null"); Application app = store.create(appDescStream); @@ -199,6 +212,7 @@ public class ApplicationManager // The following methods are fully synchronized to guard against remote vs. // locally induced feature service interactions. + // Installs all feature repositories required by the specified app. private synchronized boolean installAppArtifacts(Application app) throws Exception { if (app.featuresRepo().isPresent() && featuresService.getRepository(app.featuresRepo().get()) == null) { @@ -208,6 +222,7 @@ public class ApplicationManager return false; } + // Uninstalls all the feature repositories required by the specified app. private synchronized boolean uninstallAppArtifacts(Application app) throws Exception { if (app.featuresRepo().isPresent() && featuresService.getRepository(app.featuresRepo().get()) != null) { @@ -217,6 +232,7 @@ public class ApplicationManager return false; } + // Installs all features that define the specified app. private synchronized boolean installAppFeatures(Application app) throws Exception { boolean changed = false; for (String name : app.features()) { @@ -233,8 +249,10 @@ public class ApplicationManager return changed; } + // Uninstalls all features that define the specified app. private synchronized boolean uninstallAppFeatures(Application app) throws Exception { boolean changed = false; + invokeHook(deactivateHooks.get(app.id().name()), app.id()); for (String name : app.features()) { Feature feature = featuresService.getFeature(name); if (feature != null && featuresService.isInstalled(feature)) { @@ -247,4 +265,16 @@ public class ApplicationManager return changed; } + // Invokes the specified function, if not null. + private void invokeHook(Runnable hook, ApplicationId appId) { + if (hook != null) { + try { + hook.run(); + } catch (Exception e) { + log.warn("Deactivate hook for application {} encountered an error", + appId.name(), e); + } + } + } + } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java index f4d560a4..ec99c18b 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/core/impl/CoreManager.java @@ -24,6 +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.util.SharedExecutors; +import org.onosproject.app.ApplicationService; import org.onosproject.cfg.ComponentConfigService; import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationIdStore; @@ -48,7 +49,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.isNullOrEmpty; import static org.onosproject.security.AppGuard.checkPermission; -import static org.onosproject.security.AppPermission.Type.*; +import static org.onosproject.security.AppPermission.Type.APP_READ; @@ -71,6 +72,9 @@ public class CoreManager implements CoreService { protected IdBlockStore idBlockStore; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ApplicationService appService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected ComponentConfigService cfgService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -111,28 +115,24 @@ public class CoreManager implements CoreService { @Override public Version version() { checkPermission(APP_READ); - return version; } @Override public Set<ApplicationId> getAppIds() { checkPermission(APP_READ); - return applicationIdStore.getAppIds(); } @Override public ApplicationId getAppId(Short id) { checkPermission(APP_READ); - return applicationIdStore.getAppId(id); } @Override public ApplicationId getAppId(String name) { checkPermission(APP_READ); - return applicationIdStore.getAppId(name); } @@ -144,6 +144,13 @@ public class CoreManager implements CoreService { } @Override + public ApplicationId registerApplication(String name, Runnable preDeactivate) { + ApplicationId id = registerApplication(name); + appService.registerDeactivateHook(id, preDeactivate); + return id; + } + + @Override public IdGenerator getIdGenerator(String topic) { IdBlockAllocator allocator = new StoreBasedIdBlockAllocator(topic, idBlockStore); return new BlockAllocatorBasedIdGenerator(allocator); @@ -185,10 +192,10 @@ public class CoreManager implements CoreService { */ private static Integer getIntegerProperty(Dictionary<?, ?> properties, String propertyName) { - Integer value = null; + Integer value; try { String s = (String) properties.get(propertyName); - value = isNullOrEmpty(s) ? value : Integer.parseInt(s.trim()); + value = isNullOrEmpty(s) ? null : Integer.parseInt(s.trim()); } catch (NumberFormatException | ClassCastException e) { value = null; } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java index fa90eb65..a498b3f4 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/BasicDeviceOperator.java @@ -51,7 +51,7 @@ public final class BasicDeviceOperator implements ConfigOperator { * @return DeviceDescription based on both sources */ public static DeviceDescription combine(BasicDeviceConfig bdc, DeviceDescription descr) { - if (bdc == null) { + if (bdc == null || descr == null) { return descr; } @@ -61,7 +61,7 @@ public final class BasicDeviceOperator implements ConfigOperator { } SparseAnnotations sa = combine(bdc, descr.annotations()); - return new DefaultDeviceDescription(descr.deviceURI(), type, descr.manufacturer(), + return new DefaultDeviceDescription(descr.deviceUri(), type, descr.manufacturer(), descr.hwVersion(), descr.swVersion(), descr.serialNumber(), descr.chassisId(), sa); } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java index 9215d3a0..03281bef 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java @@ -740,7 +740,7 @@ public class DeviceManager Device dev = getDevice(did); DeviceDescription desc = (dev == null) ? null : BasicDeviceOperator.descriptionOf(dev); desc = BasicDeviceOperator.combine(cfg, desc); - if (getProvider(did) != null) { + if (desc != null && getProvider(did) != null) { de = store.createOrUpdateDevice(getProvider(did).id(), did, desc); } } @@ -754,7 +754,7 @@ public class DeviceManager OpticalPortConfig opc = networkConfigService.getConfig(cpt, OpticalPortConfig.class); PortDescription desc = OpticalPortOperator.descriptionOf(dpt); desc = OpticalPortOperator.combine(opc, desc); - if (getProvider(did) != null) { + if (desc != null && getProvider(did) != null) { de = store.updatePortStatus(getProvider(did).id(), did, desc); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java index 1473f33f..f48b8366 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java @@ -192,10 +192,7 @@ public class HostManager @Override public void removeHost(HostId hostId) { checkNotNull(hostId, HOST_ID_NULL); - HostEvent event = store.removeHost(hostId); - if (event != null) { - post(event); - } + store.removeHost(hostId); } // Personalized host provider service issued to the supplied provider. @@ -211,11 +208,8 @@ public class HostManager checkNotNull(hostId, HOST_ID_NULL); checkValidity(); hostDescription = validateHost(hostDescription, hostId); - HostEvent event = store.createOrUpdateHost(provider().id(), hostId, + store.createOrUpdateHost(provider().id(), hostId, hostDescription, replaceIps); - if (event != null) { - post(event); - } } // returns a HostDescription made from the union of the BasicHostConfig @@ -231,20 +225,14 @@ public class HostManager public void hostVanished(HostId hostId) { checkNotNull(hostId, HOST_ID_NULL); checkValidity(); - HostEvent event = store.removeHost(hostId); - if (event != null) { - post(event); - } + store.removeHost(hostId); } @Override public void removeIpFromHost(HostId hostId, IpAddress ipAddress) { checkNotNull(hostId, HOST_ID_NULL); checkValidity(); - HostEvent event = store.removeIp(hostId, ipAddress); - if (event != null) { - post(event); - } + store.removeIp(hostId, ipAddress); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java index 5ebc812e..ebf681a2 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java @@ -48,9 +48,9 @@ import org.onosproject.net.intent.PartitionEvent; import org.onosproject.net.intent.PartitionEventListener; import org.onosproject.net.intent.PartitionService; import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.resource.link.LinkResourceEvent; -import org.onosproject.net.resource.link.LinkResourceListener; -import org.onosproject.net.resource.link.LinkResourceService; +import org.onosproject.net.newresource.ResourceEvent; +import org.onosproject.net.newresource.ResourceListener; +import org.onosproject.net.newresource.ResourceService; import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyListener; import org.onosproject.net.topology.TopologyService; @@ -60,6 +60,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -101,7 +102,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { protected TopologyService topologyService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkResourceService resourceManager; + protected ResourceService resourceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceService deviceService; @@ -122,8 +123,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { .newScheduledThreadPool(1); private TopologyListener listener = new InternalTopologyListener(); - private LinkResourceListener linkResourceListener = - new InternalLinkResourceListener(); + private ResourceListener resourceListener = new InternalResourceListener(); private DeviceListener deviceListener = new InternalDeviceListener(); private HostListener hostListener = new InternalHostListener(); private PartitionEventListener partitionListener = new InternalPartitionListener(); @@ -134,7 +134,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { @Activate public void activate() { topologyService.addListener(listener); - resourceManager.addListener(linkResourceListener); + resourceService.addListener(resourceListener); deviceService.addListener(deviceListener); hostService.addListener(hostListener); partitionService.addListener(partitionListener); @@ -144,7 +144,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { @Deactivate public void deactivate() { topologyService.removeListener(listener); - resourceManager.removeListener(linkResourceListener); + resourceService.removeListener(resourceListener); deviceService.removeListener(deviceListener); hostService.removeListener(hostListener); partitionService.removeListener(partitionListener); @@ -299,35 +299,22 @@ public class ObjectiveTracker implements ObjectiveTrackerService { } } - /** - * Internal re-actor to resource available events. - */ - private class InternalLinkResourceListener implements LinkResourceListener { + private class InternalResourceListener implements ResourceListener { @Override - public void event(LinkResourceEvent event) { - executorService.execute(new ResourceAvailableHandler(event)); - } - } - - /* - * Re-dispatcher of resource available events. - */ - private class ResourceAvailableHandler implements Runnable { - - private final LinkResourceEvent event; - - ResourceAvailableHandler(LinkResourceEvent event) { - this.event = event; - } + public void event(ResourceEvent event) { + Optional<Class<?>> linkEvent = event.subject().components().stream() + .map(Object::getClass) + .filter(x -> x == LinkKey.class) + .findFirst(); + if (linkEvent.isPresent()) { + executorService.execute(() -> { + if (delegate == null) { + return; + } - @Override - public void run() { - // If there is no delegate, why bother? Just bail. - if (delegate == null) { - return; + delegate.triggerCompile(Collections.emptySet(), true); + }); } - - delegate.triggerCompile(Collections.emptySet(), true); } } 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 10fe75ea..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 @@ -18,16 +18,22 @@ package org.onosproject.net.newresource.impl; import com.google.common.annotations.Beta; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +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.onosproject.event.AbstractListenerManager; import org.onosproject.net.newresource.ResourceAdminService; import org.onosproject.net.newresource.ResourceAllocation; import org.onosproject.net.newresource.ResourceConsumer; +import org.onosproject.net.newresource.ResourceEvent; +import org.onosproject.net.newresource.ResourceListener; import org.onosproject.net.newresource.ResourceService; import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.newresource.ResourceStore; +import org.onosproject.net.newresource.ResourceStoreDelegate; import java.util.ArrayList; import java.util.Collection; @@ -44,20 +50,32 @@ import static com.google.common.base.Preconditions.checkNotNull; @Component(immediate = true) @Service @Beta -public final class ResourceManager implements ResourceService, ResourceAdminService { +public final class ResourceManager extends AbstractListenerManager<ResourceEvent, ResourceListener> + implements ResourceService, ResourceAdminService { @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected ResourceStore store; + private final ResourceStoreDelegate delegate = new InternalStoreDelegate(); + + @Activate + public void activate() { + store.setDelegate(delegate); + eventDispatcher.addSink(ResourceEvent.class, listenerRegistry); + } + + @Deactivate + public void deactivate() { + store.unsetDelegate(delegate); + eventDispatcher.removeSink(ResourceEvent.class); + } + @Override public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<ResourcePath> resources) { checkNotNull(consumer); checkNotNull(resources); - // TODO: implement support of resource hierarchy - // allocation for a particular resource implies allocations for all of the sub-resources need to be done - boolean success = store.allocate(resources, consumer); if (!success) { return ImmutableList.of(); @@ -151,7 +169,7 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ 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); } @@ -161,7 +179,14 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ 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); } + + private class InternalStoreDelegate implements ResourceStoreDelegate { + @Override + public void notify(ResourceEvent event) { + post(event); + } + } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java index 4067d017..143f8c2b 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java @@ -36,7 +36,7 @@ import static org.onlab.util.Tools.groupedThreads; /** * A class registering resources when they are detected. */ -@Component(immediate = true, enabled = false) +@Component(immediate = true) @Beta public final class ResourceRegistrar { 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/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java index 25a2640d..5ecf2806 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java @@ -53,6 +53,7 @@ import org.slf4j.Logger; import java.nio.ByteBuffer; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @@ -199,11 +200,49 @@ public class ProxyArpManager implements ProxyArpService { return; } + // If the packets has a vlanId look if there are some other + // interfaces in the configuration on the same vlan and broadcast + // the packet out just of through those interfaces. + VlanId vlanId = context.vlan(); + + Set<Interface> filteredVlanInterfaces = + filterVlanInterfacesNoIp(interfaceService.getInterfacesByVlan(vlanId)); + + if (vlanId != null + && !vlanId.equals(VlanId.NONE) + && confContainsVlans(vlanId, context.inPort())) { + vlanFlood(context.packet(), filteredVlanInterfaces, context.inPort); + return; + } + // The request couldn't be resolved. // Flood the request on all ports except the incoming port. flood(context.packet(), context.inPort()); } + private Set<Interface> filterVlanInterfacesNoIp(Set<Interface> vlanInterfaces) { + return vlanInterfaces + .stream() + .filter(intf -> intf.ipAddresses().isEmpty()) + .collect(Collectors.toSet()); + } + + /** + * States if the interface configuration contains more than one interface configured + * on a specific vlan, including the interface passed as argument. + * + * @param vlanId the vlanid to look for in the interface configuration + * @param connectPoint the connect point to exclude from the search + * @return true if interfaces are found. False otherwise + */ + private boolean confContainsVlans(VlanId vlanId, ConnectPoint connectPoint) { + Set<Interface> vlanInterfaces = interfaceService.getInterfacesByVlan(vlanId); + return interfaceService.getInterfacesByVlan(vlanId) + .stream() + .anyMatch(intf -> intf.connectPoint().equals(connectPoint) && intf.ipAddresses().isEmpty()) + && vlanInterfaces.size() > 1; + } + /** * Builds and sends a reply message given a request context and the resolved * MAC address to answer with. @@ -259,14 +298,29 @@ public class ProxyArpManager implements ProxyArpService { /** * Returns whether the given port has any IP addresses configured or not. * - * @param port the port to check + * @param connectPoint the port to check * @return true if the port has at least one IP address configured, - * otherwise false + * false otherwise + */ + private boolean hasIpAddress(ConnectPoint connectPoint) { + return interfaceService.getInterfacesByPort(connectPoint) + .stream() + .flatMap(intf -> intf.ipAddresses().stream()) + .findAny() + .isPresent(); + } + + /** + * Returns whether the given port has any VLAN configured or not. + * + * @param connectPoint the port to check + * @return true if the port has at least one VLAN configured, + * false otherwise */ - private boolean hasIpAddress(ConnectPoint port) { - return interfaceService.getInterfacesByPort(port) + private boolean hasVlan(ConnectPoint connectPoint) { + return interfaceService.getInterfacesByPort(connectPoint) .stream() - .map(intf -> intf.ipAddresses()) + .filter(intf -> !intf.vlan().equals(VlanId.NONE)) .findAny() .isPresent(); } @@ -322,6 +376,30 @@ public class ProxyArpManager implements ProxyArpService { } /** + * Flood the arp request at all edges on a specifc VLAN. + * + * @param request the arp request + * @param dsts the destination interfaces + * @param inPort the connect point the arp request was received on + */ + private void vlanFlood(Ethernet request, Set<Interface> dsts, ConnectPoint inPort) { + TrafficTreatment.Builder builder = null; + ByteBuffer buf = ByteBuffer.wrap(request.serialize()); + + for (Interface intf : dsts) { + ConnectPoint cPoint = intf.connectPoint(); + if (cPoint.equals(inPort)) { + continue; + } + + builder = DefaultTrafficTreatment.builder(); + builder.setOutput(cPoint.port()); + packetService.emit(new DefaultOutboundPacket(cPoint.deviceId(), + builder.build(), buf)); + } + } + + /** * Flood the arp request at all edges in the network. * * @param request the arp request @@ -332,7 +410,9 @@ public class ProxyArpManager implements ProxyArpService { ByteBuffer buf = ByteBuffer.wrap(request.serialize()); for (ConnectPoint connectPoint : edgeService.getEdgePoints()) { - if (hasIpAddress(connectPoint) || connectPoint.equals(inPort)) { + if (hasIpAddress(connectPoint) + || hasVlan(connectPoint) + || connectPoint.equals(inPort)) { continue; } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java index 6515ef31..f18c56dc 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java @@ -255,7 +255,7 @@ public class FlowStatisticManager implements FlowStatisticService { Instruction.Type instType) {
checkPermission(STATISTIC_READ);
- List<TypedFlowEntryWithLoad> retTFEL = new ArrayList<>();
+ List<TypedFlowEntryWithLoad> retTfel = new ArrayList<>();
Set<FlowEntry> currentStats;
Set<FlowEntry> previousStats;
@@ -264,11 +264,11 @@ public class FlowStatisticManager implements FlowStatisticService { synchronized (flowStatisticStore) {
currentStats = flowStatisticStore.getCurrentFlowStatistic(cp);
if (currentStats == null) {
- return retTFEL;
+ return retTfel;
}
previousStats = flowStatisticStore.getPreviousFlowStatistic(cp);
if (previousStats == null) {
- return retTFEL;
+ return retTfel;
}
// copy to local flow entry set
typedStatistics = new TypedStatistics(currentStats, previousStats);
@@ -291,7 +291,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -302,7 +302,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -313,7 +313,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.midPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -324,7 +324,7 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.longPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
@@ -335,11 +335,11 @@ public class FlowStatisticManager implements FlowStatisticService { List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
isAllInstType, instType, TypedFlowEntryWithLoad.avgPollInterval());
if (fel.size() > 0) {
- retTFEL.addAll(fel);
+ retTfel.addAll(fel);
}
}
- return retTFEL;
+ return retTfel;
}
private List<TypedFlowEntryWithLoad> typedFlowEntryLoadByInstInternal(ConnectPoint cp,
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java index 1ce31ac3..a99fd216 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java @@ -15,6 +15,7 @@ */ package org.onosproject.app.impl; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.junit.After; import org.junit.Before; @@ -24,11 +25,11 @@ import org.onosproject.app.ApplicationListener; import org.onosproject.app.ApplicationState; import org.onosproject.app.ApplicationStoreAdapter; import org.onosproject.common.app.ApplicationArchive; +import org.onosproject.common.event.impl.TestEventDispatcher; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; import org.onosproject.core.DefaultApplication; import org.onosproject.core.DefaultApplicationId; -import org.onosproject.common.event.impl.TestEventDispatcher; import java.io.InputStream; import java.net.URI; @@ -36,7 +37,7 @@ import java.util.HashSet; import java.util.Optional; import java.util.Set; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import static org.onosproject.app.ApplicationEvent.Type.*; import static org.onosproject.app.ApplicationState.ACTIVE; import static org.onosproject.app.ApplicationState.INSTALLED; @@ -53,6 +54,8 @@ public class ApplicationManagerTest { private ApplicationManager mgr = new ApplicationManager(); private ApplicationListener listener = new TestListener(); + private boolean deactivated = false; + @Before public void setUp() { injectEventDispatcher(mgr, new TestEventDispatcher()); @@ -88,6 +91,11 @@ public class ApplicationManagerTest { assertEquals("incorrect app count", 1, mgr.getApplications().size()); assertEquals("incorrect app", app, mgr.getApplication(APP_ID)); assertEquals("incorrect app state", INSTALLED, mgr.getState(APP_ID)); + mgr.registerDeactivateHook(app.id(), this::deactivateHook); + } + + private void deactivateHook() { + deactivated = true; } @Test @@ -102,6 +110,7 @@ public class ApplicationManagerTest { install(); mgr.activate(APP_ID); assertEquals("incorrect app state", ACTIVE, mgr.getState(APP_ID)); + assertFalse("preDeactivate hook wrongly called", deactivated); } @Test @@ -109,6 +118,7 @@ public class ApplicationManagerTest { activate(); mgr.deactivate(APP_ID); assertEquals("incorrect app state", INSTALLED, mgr.getState(APP_ID)); + assertTrue("preDeactivate hook not called", deactivated); } @@ -129,7 +139,7 @@ public class ApplicationManagerTest { @Override public Application create(InputStream appDescStream) { app = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, ROLE, PERMS, - Optional.of(FURL), FEATURES); + Optional.of(FURL), FEATURES, ImmutableList.of()); state = INSTALLED; delegate.notify(new ApplicationEvent(APP_INSTALLED, app)); return app; @@ -168,6 +178,11 @@ public class ApplicationManagerTest { state = INSTALLED; delegate.notify(new ApplicationEvent(APP_DEACTIVATED, app)); } + + @Override + public ApplicationId getId(String name) { + return new DefaultApplicationId(0, name); + } } private class TestFeaturesService extends FeaturesServiceAdapter { diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java index 92c6c931..c5a6cabd 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java @@ -20,6 +20,7 @@ import com.google.common.collect.Sets; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.onlab.junit.TestTools; import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; import org.onlab.packet.VlanId; @@ -129,13 +130,15 @@ public class HostManagerTest { } private void validateEvents(Enum... types) { - int i = 0; - assertEquals("wrong events received", types.length, listener.events.size()); - for (Event event : listener.events) { - assertEquals("incorrect event type", types[i], event.type()); - i++; - } - listener.events.clear(); + TestTools.assertAfter(100, () -> { + int i = 0; + assertEquals("wrong events received", types.length, listener.events.size()); + for (Event event : listener.events) { + assertEquals("incorrect event type", types[i], event.type()); + i++; + } + listener.events.clear(); + }); } @Test 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 58fa1292..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 @@ -16,7 +16,6 @@ package org.onosproject.net.intent.impl; import java.util.Collection; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -38,8 +37,9 @@ import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.Key; import org.onosproject.net.intent.MockIdGenerator; import org.onosproject.net.link.LinkEvent; -import org.onosproject.net.resource.link.LinkResourceEvent; -import org.onosproject.net.resource.link.LinkResourceListener; +import org.onosproject.net.newresource.ResourceEvent; +import org.onosproject.net.newresource.ResourceListener; +import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.topology.Topology; import org.onosproject.net.topology.TopologyEvent; import org.onosproject.net.topology.TopologyListener; @@ -52,6 +52,8 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static org.onosproject.net.LinkKey.linkKey; +import static org.onosproject.net.newresource.ResourceEvent.Type.*; import static org.onosproject.net.NetTestTools.APP_ID; import static org.onosproject.net.NetTestTools.device; import static org.onosproject.net.NetTestTools.link; @@ -67,7 +69,7 @@ public class ObjectiveTrackerTest { private List<Event> reasons; private TopologyListener listener; private DeviceListener deviceListener; - private LinkResourceListener linkResourceListener; + private ResourceListener resourceListener; private IdGenerator mockGenerator; /** @@ -84,7 +86,7 @@ public class ObjectiveTrackerTest { reasons = new LinkedList<>(); listener = TestUtils.getField(tracker, "listener"); deviceListener = TestUtils.getField(tracker, "deviceListener"); - linkResourceListener = TestUtils.getField(tracker, "linkResourceListener"); + resourceListener = TestUtils.getField(tracker, "resourceListener"); mockGenerator = new MockIdGenerator(); Intent.bindIdGenerator(mockGenerator); } @@ -228,10 +230,9 @@ public class ObjectiveTrackerTest { */ @Test public void testResourceEvent() throws Exception { - LinkResourceEvent event = new LinkResourceEvent( - LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE, - new HashSet<>()); - linkResourceListener.event(event); + ResourceEvent event = new ResourceEvent(RESOURCE_ADDED, + ResourcePath.discrete(linkKey(link("a", 1, "b", 1)))); + resourceListener.event(event); assertThat( delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS), 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 06b2c81e..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 @@ -19,6 +19,7 @@ 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.ResourceListener; import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.newresource.ResourceService; @@ -89,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); } @@ -97,4 +98,10 @@ class MockResourceService implements ResourceService { public boolean isAvailable(ResourcePath resource) { return true; } + + @Override + public void addListener(ResourceListener listener) {} + + @Override + public void removeListener(ResourceListener listener) {} } 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 3e806a73..70fdb406 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 @@ -15,7 +15,6 @@ */ package org.onosproject.net.proxyarp.impl; -import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; @@ -48,7 +47,7 @@ import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; -import org.onosproject.net.edgeservice.impl.EdgeManager; +import org.onosproject.net.edge.EdgePortService; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.flow.instructions.Instruction; @@ -67,6 +66,7 @@ import org.onosproject.net.proxyarp.ProxyArpStoreDelegate; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -88,47 +88,65 @@ import static org.junit.Assert.assertTrue; */ public class ProxyArpManagerTest { - private static final int NUM_DEVICES = 6; + private static final int NUM_DEVICES = 10; private static final int NUM_PORTS_PER_DEVICE = 3; - private static final int NUM_ADDRESS_PORTS = NUM_DEVICES / 2; - private static final int NUM_FLOOD_PORTS = 3; + private static final int LAST_CONF_DEVICE_INTF_VLAN_IP = 3; + private static final int LAST_CONF_DEVICE_INTF_VLAN = 6; 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 Ip6Address IP3 = Ip6Address.valueOf("1000:ffff::1"); + private static final Ip6Address IP4 = Ip6Address.valueOf("1000:ffff::2"); private static final ProviderId PID = new ProviderId("of", "foo"); private static final VlanId VLAN1 = VlanId.vlanId((short) 1); 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 VlanId VLAN10 = VlanId.vlanId((short) 10); + + private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01"); + private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02"); + private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03"); + private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04"); + private static final MacAddress MAC10 = MacAddress.valueOf("00:00:00:00:00:0A"); + 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 HID10 = HostId.hostId(MAC10, VLAN10); + 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); + private static final PortNumber P1 = PortNumber.portNumber(1); + private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L); - private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes(); - //Return values used for various functions of the TestPacketService inner class. - private boolean isEdgePointReturn; - private List<ConnectPoint> getEdgePointsNoArg; + private final byte[] zeroMacAddress = MacAddress.ZERO.toBytes(); + + // The first three devices in the topology have interfaces configured + // with VLANs and IPs + private final List<ConnectPoint> configIpCPoints = new ArrayList<>(); + // Other three devices in the topology (from 4 to 6) have interfaces + // configured only with VLANs + private final List<ConnectPoint> configVlanCPoints = new ArrayList<>(); + + // Remaining devices in the network (id > 6) don't have any interface + // configured. + private final List<ConnectPoint> noConfigCPoints = new ArrayList<>(); private ProxyArpManager proxyArp; private TestPacketService packetService; private DeviceService deviceService; + private EdgePortService edgePortService; private LinkService linkService; private HostService hostService; private InterfaceService interfaceService; @@ -140,20 +158,27 @@ public class ProxyArpManagerTest { proxyArp.packetService = packetService; proxyArp.store = new TestProxyArpStoreAdapter(); - proxyArp.edgeService = new TestEdgePortService(); - - // Create a host service mock here. Must be replayed by tests once the - // expectations have been set up + // Create a host service mock here. hostService = createMock(HostService.class); proxyArp.hostService = hostService; + // Create an edge port service. + edgePortService = createMock(EdgePortService.class); + proxyArp.edgeService = edgePortService; + + // Create interface service interfaceService = createMock(InterfaceService.class); proxyArp.interfaceService = interfaceService; + // Create the topology createTopology(); proxyArp.deviceService = deviceService; proxyArp.linkService = linkService; + setupNoConfigCPoints(); + setupconfigIpCPoints(); + setupconfigVlanCPoints(); + proxyArp.activate(); } @@ -176,7 +201,8 @@ public class ProxyArpManagerTest { createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE); createLinks(NUM_DEVICES); - addAddressBindings(); + addIntfConfig(); + popluateEdgePortService(); } /** @@ -237,13 +263,22 @@ public class ProxyArpManagerTest { replay(linkService); } - private void addAddressBindings() { + /** + * On the first three devices two config interfaces are binded on port 1. + * The first one with VLAN1, the second one with VLAN equals to none. + * Both interfaces have an IP. + * On devices 4, 5 and 6 it's binded a config interface on port 1. + * The interface is configured with VLAN 1 and no IP. + */ + private void addIntfConfig() { Set<Interface> interfaces = Sets.newHashSet(); - for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) { + Set<Interface> vlanOneSet = new HashSet<>(); + + for (int i = 1; i <= LAST_CONF_DEVICE_INTF_VLAN_IP; i++) { ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); - // Interface address for IPv4 + // Interface addresses 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"); @@ -251,39 +286,131 @@ public class ProxyArpManagerTest { InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1); InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2); - // Interface address for IPv6 + // Interface addresses 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"); + Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::2"); InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3); InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4); + // Setting up interfaces 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, ia4), MacAddress.valueOf(2 * i), VlanId.NONE); + interfaces.add(intf1); interfaces.add(intf2); + vlanOneSet.add(intf1); + expect(interfaceService.getInterfacesByPort(cp)) .andReturn(Sets.newHashSet(intf1, intf2)).anyTimes(); } + for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) { + ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); + Interface intf1 = new Interface(cp, null, + MacAddress.NONE, + VlanId.vlanId((short) 1)); + + interfaces.add(intf1); + vlanOneSet.add(intf1); + expect(interfaceService.getInterfacesByPort(cp)) + .andReturn(Sets.newHashSet(intf1)).anyTimes(); + } + expect(interfaceService.getInterfacesByVlan(VLAN1)) + .andReturn(vlanOneSet).anyTimes(); + expect(interfaceService.getInterfacesByVlan(VLAN10)) + .andReturn(Collections.emptySet()).anyTimes(); expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes(); - for (int i = 1; i <= NUM_FLOOD_PORTS; i++) { - ConnectPoint cp = new ConnectPoint(getDeviceId(i + NUM_ADDRESS_PORTS), + for (int i = LAST_CONF_DEVICE_INTF_VLAN + 1; i <= NUM_DEVICES; i++) { + ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1); - expect(interfaceService.getInterfacesByPort(cp)) .andReturn(Collections.emptySet()).anyTimes(); } } /** + * Populates edge ports in the EdgePortService to return all port 1 + * as edge ports. + */ + private void popluateEdgePortService() { + Set<ConnectPoint> edgeConnectPoints = new HashSet<>(); + + for (int i = 1; i <= NUM_DEVICES; i++) { + for (int j = 1; j <= NUM_PORTS_PER_DEVICE; j++) { + ConnectPoint edgeConnectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + ConnectPoint noEdgeConnectPointOne = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(2)); + ConnectPoint noEdgeConnectPointTwo = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(3)); + + edgeConnectPoints.add(edgeConnectPoint); + + expect(edgePortService.isEdgePoint(edgeConnectPoint)) + .andReturn(true).anyTimes(); + expect(edgePortService.isEdgePoint(noEdgeConnectPointOne)) + .andReturn(false).anyTimes(); + expect(edgePortService.isEdgePoint(noEdgeConnectPointTwo)) + .andReturn(false).anyTimes(); + } + } + expect(edgePortService.getEdgePoints()) + .andReturn(edgeConnectPoints).anyTimes(); + + replay(edgePortService); + } + + /** + * Creates a list of connect points used to verify floodling on ports + * with no interfaces configured (all ports without interface config). + */ + private void setupNoConfigCPoints() { + for (int i = NUM_DEVICES / 2 + 2; i <= NUM_DEVICES; i++) { + ConnectPoint connectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + noConfigCPoints.add(connectPoint); + } + } + + /** + * Creates a list of connect points used to verify floodling on ports + * with interfaces configured (both VLAN and IP). + */ + private void setupconfigIpCPoints() { + for (int i = 1; i <= 3; i++) { + ConnectPoint connectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + configIpCPoints.add(connectPoint); + } + } + + /** + * Creates a list of connect points used to verify floodling on ports + * with interfaces configured (both VLAN and IP). + */ + private void setupconfigVlanCPoints() { + for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) { + ConnectPoint connectPoint = new ConnectPoint( + getDeviceId(i), + PortNumber.portNumber(1)); + configVlanCPoints.add(connectPoint); + } + } + + /** * Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the * case where the IP address is not known. * Verifies the method returns false. @@ -318,33 +445,34 @@ public class ProxyArpManagerTest { /** * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the * destination host is known. - * Verifies the correct ARP reply is sent out the correct port. + * Two host using the same VLAN are registered on the host service on devices 5 and 6. + * Host on port 6 asks for the MAC of the device on port 5. + * Since the destination mac address is known, the request is not flooded to anywhere + * and ONOS directly builds an ARP reply, sended back to the requester on device 6. + * It's verified that a proper ARP reply is received on port 1 of device 6. */ @Test public void testReplyKnown() { - //Set the return value of isEdgePoint from the edgemanager. - isEdgePointReturn = true; - - Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(4), + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES), Collections.singleton(IP1)); - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5), + Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(NUM_DEVICES - 1), Collections.singleton(IP2)); - expect(hostService.getHostsByIp(IP1)) + expect(hostService.getHostsByIp(IP2)) .andReturn(Collections.singleton(replyer)); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID1)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2); - proxyArp.reply(arpRequest, getLocation(5)); + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); assertEquals(1, packetService.packets.size()); - Ethernet arpReply = buildArp(ARP.OP_REPLY, MAC1, MAC2, IP1, IP2); - verifyPacketOut(arpReply, getLocation(5), packetService.packets.get(0)); + Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1); + verifyPacketOut(arpReply, getLocation(NUM_DEVICES), packetService.packets.get(0)); } /** @@ -354,9 +482,6 @@ public class ProxyArpManagerTest { */ @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)); @@ -370,49 +495,46 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + 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); + 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. + * Only a requestor is present (on device 6, port 1). The device has a VLAN configured + * which is not configured anywhere in the system. + * Since the destination is not known, and since the ARP request can't be sent out of + * interfaces configured, the ARP request is flooded out of ports 4 and 5. * Verifies the ARP request is flooded out the correct edge ports. */ @Test public void testReplyUnknown() { - isEdgePointReturn = true; - - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5), - Collections.singleton(IP2)); + Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES), + Collections.singleton(IP1)); - expect(hostService.getHostsByIp(IP1)) + expect(hostService.getHostsByIp(IP2)) .andReturn(Collections.emptySet()); - expect(interfaceService.getInterfacesByIp(IP2)) + expect(interfaceService.getInterfacesByIp(IP1)) .andReturn(Collections.emptySet()); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID10)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); - - //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))); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2); - proxyArp.reply(arpRequest, getLocation(6)); + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); - verifyFlood(arpRequest); + verifyFlood(arpRequest, noConfigCPoints); } /** @@ -422,9 +544,7 @@ public class ProxyArpManagerTest { */ @Test public void testReplyUnknownIpv6() { - isEdgePointReturn = true; - - Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5), + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES), Collections.singleton(IP4)); expect(hostService.getHostsByIp(IP3)) @@ -436,53 +556,111 @@ public class ProxyArpManagerTest { 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))); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); - proxyArp.reply(ndpRequest, getLocation(6)); + proxyArp.reply(ndpRequest, getLocation(NUM_DEVICES)); - verifyFlood(ndpRequest); + verifyFlood(ndpRequest, noConfigCPoints); } /** * 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. + * An host is connected on device 6, port 1 where no interfaces are defined. It sends + * ARP requests from VLAN10, not configured anywhere in the network. Another host with + * the IP address requested lives on device 5, port 1 in the network. Anyway, since the + * host uses another VLAN it's not found and the ARP packet is flooded out of port + * 4 and 5. + * * Verifies the ARP request is flooded out the correct edge ports. */ @Test public void testReplyDifferentVlan() { - - Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN2, getLocation(4), + Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES), Collections.singleton(IP1)); - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5), + Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN2, getLocation(NUM_DEVICES - 1), Collections.singleton(IP2)); - expect(hostService.getHostsByIp(IP1)) + expect(hostService.getHostsByIp(IP2)) .andReturn(Collections.singleton(replyer)); - expect(interfaceService.getInterfacesByIp(IP2)) + expect(interfaceService.getInterfacesByIp(IP1)) .andReturn(Collections.emptySet()); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID10)).andReturn(requestor); + + replay(hostService); + replay(interfaceService); + + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2); + + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); + + verifyFlood(arpRequest, noConfigCPoints); + } + + /** + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the + * a vlan packet comes in from a port without interfaces configured. The destination + * host is unknown for that IP address and there are some interfaces configured on + * the same vlan. + * It's expected to see the ARP request going out through ports with no interfaces + * configured, devices 4 and 5, port 1. + * + * Verifies the ARP request is flooded out the correct edge ports. + */ + @Test + public void testConfiguredVlan() { + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES), + Collections.singleton(IP1)); + + expect(hostService.getHostsByIp(IP2)) + .andReturn(Collections.emptySet()); + expect(interfaceService.getInterfacesByIp(IP1)) + .andReturn(Collections.emptySet()); + expect(hostService.getHost(HID1)).andReturn(requestor); + + replay(hostService); + replay(interfaceService); + + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2); + + proxyArp.reply(arpRequest, getLocation(NUM_DEVICES)); + + verifyFlood(arpRequest, noConfigCPoints); + } + + /** + * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the + * a vlan packet comes in from a port without interfaces configured. The destination + * host is not known for that IP address and there are some interfaces configured on + * the same vlan. + * It's expected to see the ARP request going out through ports with no interfaces + * configured, devices 4 and 5, port 1. + * + * Verifies the ARP request is flooded out the correct edge ports. + */ + @Test + public void testConfiguredVlanOnInterfaces() { + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(6), + Collections.singleton(IP1)); + + expect(hostService.getHostsByIp(IP2)) + .andReturn(Collections.emptySet()); + expect(interfaceService.getInterfacesByIp(IP1)) + .andReturn(Collections.emptySet()); + expect(hostService.getHost(HID1)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2); - //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(arpRequest, getLocation(6)); - verifyFlood(arpRequest); + verifyFlood(arpRequest, configVlanCPoints); } /** @@ -493,13 +671,12 @@ public class ProxyArpManagerTest { */ @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), + Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES), Collections.singleton(IP4)); + Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(NUM_DEVICES - 1), + Collections.singleton(IP3)); + expect(hostService.getHostsByIp(IP3)) .andReturn(Collections.singleton(replyer)); expect(interfaceService.getInterfacesByIp(IP4)) @@ -509,17 +686,13 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + 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)); + proxyArp.reply(ndpRequest, getLocation(NUM_DEVICES)); - verifyFlood(ndpRequest); + verifyFlood(ndpRequest, noConfigCPoints); } /** @@ -533,29 +706,29 @@ public class ProxyArpManagerTest { MacAddress firstMac = MacAddress.valueOf(1L); MacAddress secondMac = MacAddress.valueOf(2L); - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1, + Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1, Collections.singleton(theirIp)); - expect(hostService.getHost(HID2)).andReturn(requestor); + expect(hostService.getHost(HID1)).andReturn(requestor); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourFirstIp); - isEdgePointReturn = true; + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourFirstIp); + proxyArp.reply(arpRequest, LOC1); assertEquals(1, packetService.packets.size()); - Ethernet arpReply = buildArp(ARP.OP_REPLY, firstMac, MAC2, ourFirstIp, theirIp); + Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, firstMac, MAC1, ourFirstIp, theirIp); verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); // Test a request for the second address on that port packetService.packets.clear(); - arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourSecondIp); + arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourSecondIp); proxyArp.reply(arpRequest, LOC1); assertEquals(1, packetService.packets.size()); - arpReply = buildArp(ARP.OP_REPLY, secondMac, MAC2, ourSecondIp, theirIp); + arpReply = buildArp(ARP.OP_REPLY, VLAN1, secondMac, MAC1, ourSecondIp, theirIp); verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); } @@ -566,7 +739,7 @@ public class ProxyArpManagerTest { public void testReplyToRequestForUsIpv6() { Ip6Address theirIp = Ip6Address.valueOf("1000::ffff"); Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1"); - Ip6Address ourSecondIp = Ip6Address.valueOf("2000::1"); + Ip6Address ourSecondIp = Ip6Address.valueOf("2000::2"); MacAddress firstMac = MacAddress.valueOf(1L); MacAddress secondMac = MacAddress.valueOf(2L); @@ -579,37 +752,37 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC2, - MacAddress.valueOf("33:33:ff:00:00:01"), - theirIp, - ourFirstIp); - isEdgePointReturn = true; + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC2, + MacAddress.valueOf("33:33:ff:00:00:01"), + theirIp, + ourFirstIp); + proxyArp.reply(ndpRequest, LOC1); assertEquals(1, packetService.packets.size()); - Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT, - firstMac, - MAC2, - ourFirstIp, - theirIp); + 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); + 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); + ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT, + secondMac, + MAC2, + ourSecondIp, + theirIp); verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0)); } @@ -624,14 +797,14 @@ public class ProxyArpManagerTest { Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254"); // Request for a valid external IP address but coming in the wrong port - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC1, null, theirIp, + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, Ip4Address.valueOf("10.0.3.1")); proxyArp.reply(arpRequest, LOC1); assertEquals(0, packetService.packets.size()); // Request for a valid internal IP address but coming in an external port packetService.packets.clear(); - arpRequest = buildArp(ARP.OP_REQUEST, MAC1, null, theirIp, IP1); + arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, IP1); proxyArp.reply(arpRequest, LOC1); assertEquals(0, packetService.packets.size()); } @@ -646,21 +819,21 @@ public class ProxyArpManagerTest { 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")); + 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); + 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()); } @@ -685,9 +858,8 @@ public class ProxyArpManagerTest { // This is a request from something inside our network (like a BGP // daemon) to an external host. - Ethernet arpRequest = buildArp(ARP.OP_REQUEST, ourMac, null, ourIp, theirIp); + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, ourMac, null, ourIp, theirIp); //Ensure the packet is allowed through (it is not to an internal port) - isEdgePointReturn = true; proxyArp.reply(arpRequest, getLocation(5)); assertEquals(1, packetService.packets.size()); @@ -722,14 +894,11 @@ public class ProxyArpManagerTest { // 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; + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + ourMac, + MacAddress.valueOf("33:33:ff:00:00:01"), + ourIp, + theirIp); proxyArp.reply(ndpRequest, getLocation(5)); assertEquals(1, packetService.packets.size()); @@ -758,7 +927,7 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1); + Ethernet arpRequest = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1); proxyArp.forward(arpRequest, LOC2); @@ -785,9 +954,9 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION, + MAC4, SOLICITED_MAC3, + IP4, IP3); proxyArp.forward(ndpRequest, LOC2); @@ -804,22 +973,15 @@ public class ProxyArpManagerTest { */ @Test public void testForwardFlood() { - expect(hostService.getHost(HID1)).andReturn(null); + expect(hostService.getHost(HID2)).andReturn(null); replay(hostService); replay(interfaceService); - Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1); - - //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))); + Ethernet arpRequest = buildArp(ARP.OP_REPLY, VLAN1, MAC1, MAC2, IP1, IP2); - proxyArp.forward(arpRequest, getLocation(6)); + proxyArp.forward(arpRequest, getLocation(NUM_DEVICES)); - verifyFlood(arpRequest); + verifyFlood(arpRequest, noConfigCPoints); } /** @@ -833,20 +995,13 @@ public class ProxyArpManagerTest { replay(hostService); replay(interfaceService); - Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION, - MAC4, SOLICITED_MAC3, - IP4, IP3); + 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(NUM_DEVICES)); - proxyArp.forward(ndpRequest, getLocation(6)); - - verifyFlood(ndpRequest); + verifyFlood(ndpRequest, noConfigCPoints); } /** @@ -854,21 +1009,20 @@ public class ProxyArpManagerTest { * except for the input port. * * @param packet the packet that was expected to be flooded + * @param connectPoints the connectPoints where the outpacket should be + * observed */ - private void verifyFlood(Ethernet packet) { + private void verifyFlood(Ethernet packet, List<ConnectPoint> connectPoints) { + // There should be 1 less than NUM_FLOOD_PORTS; the inPort should be excluded. - assertEquals(NUM_FLOOD_PORTS - 1, packetService.packets.size()); + assertEquals(connectPoints.size() - 1, packetService.packets.size()); Collections.sort(packetService.packets, (o1, o2) -> o1.sendThrough().uri().compareTo(o2.sendThrough().uri())); - - for (int i = 0; i < NUM_FLOOD_PORTS - 1; i++) { - ConnectPoint cp = new ConnectPoint(getDeviceId(NUM_ADDRESS_PORTS + i + 1), - PortNumber.portNumber(1)); - + for (int i = 0; i < connectPoints.size() - 1; i++) { OutboundPacket outboundPacket = packetService.packets.get(i); - verifyPacketOut(packet, cp, outboundPacket); + verifyPacketOut(packet, connectPoints.get(i), outboundPacket); } } @@ -913,8 +1067,8 @@ public class ProxyArpManagerTest { * @param dstIp destination IP address * @return the ARP packet */ - private Ethernet buildArp(short opcode, MacAddress srcMac, MacAddress dstMac, - Ip4Address srcIp, Ip4Address dstIp) { + private Ethernet buildArp(short opcode, VlanId vlanId, MacAddress srcMac, + MacAddress dstMac, Ip4Address srcIp, Ip4Address dstIp) { Ethernet eth = new Ethernet(); if (dstMac == null) { @@ -925,7 +1079,7 @@ public class ProxyArpManagerTest { eth.setSourceMACAddress(srcMac); eth.setEtherType(Ethernet.TYPE_ARP); - eth.setVlanID(VLAN1.toShort()); + eth.setVlanID(vlanId.toShort()); ARP arp = new ARP(); arp.setOpCode(opcode); @@ -937,7 +1091,7 @@ public class ProxyArpManagerTest { arp.setSenderHardwareAddress(srcMac.toBytes()); if (dstMac == null) { - arp.setTargetHardwareAddress(ZERO_MAC_ADDRESS); + arp.setTargetHardwareAddress(zeroMacAddress); } else { arp.setTargetHardwareAddress(dstMac.toBytes()); } @@ -959,7 +1113,7 @@ public class ProxyArpManagerTest { * @param dstIp destination IP address * @return the NDP packet */ - private Ethernet buildNDP(byte type, MacAddress srcMac, MacAddress dstMac, + private Ethernet buildNdp(byte type, MacAddress srcMac, MacAddress dstMac, Ip6Address srcIp, Ip6Address dstIp) { assertThat(type, anyOf( is(ICMP6.NEIGHBOR_SOLICITATION), @@ -1019,19 +1173,6 @@ public class ProxyArpManagerTest { } - class TestEdgePortService extends EdgeManager { - - @Override - public boolean isEdgePoint(ConnectPoint connectPoint) { - return isEdgePointReturn; - } - - @Override - public Iterable<ConnectPoint> getEdgePoints() { - return getEdgePointsNoArg; - } - } - private class TestProxyArpStoreAdapter implements ProxyArpStore { @Override public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) { 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 6764c222..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 @@ -17,7 +17,9 @@ package org.onosproject.store.app; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableSet; - +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +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; @@ -37,6 +39,7 @@ import org.onosproject.common.app.ApplicationArchive; import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationIdStore; +import org.onosproject.core.CoreService; import org.onosproject.core.DefaultApplication; import org.onosproject.security.Permission; import org.onosproject.store.cluster.messaging.ClusterCommunicationService; @@ -61,6 +64,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Function; +import static com.google.common.collect.Multimaps.newSetMultimap; +import static com.google.common.collect.Multimaps.synchronizedSetMultimap; import static com.google.common.io.ByteStreams.toByteArray; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.onlab.util.Tools.groupedThreads; @@ -115,6 +120,14 @@ public class GossipApplicationStore extends ApplicationArchive @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected ApplicationIdStore idStore; + // Multimap to track which apps are required by others apps + // app -> { required-by, ... } + // Apps explicitly activated will be required by the CORE app + private final Multimap<ApplicationId, ApplicationId> requiredBy = + synchronizedSetMultimap(newSetMultimap(Maps.newHashMap(), Sets::newHashSet)); + + private ApplicationId coreAppId; + @Activate public void activate() { KryoNamespace.Builder serializer = KryoNamespace.newBuilder() @@ -128,16 +141,16 @@ public class GossipApplicationStore extends ApplicationArchive groupedThreads("onos/store/app", "message-handler")); clusterCommunicator.<String, byte[]>addSubscriber(APP_BITS_REQUEST, - bytes -> new String(bytes, Charsets.UTF_8), - name -> { - try { - return toByteArray(getApplicationInputStream(name)); - } catch (IOException e) { - throw new StorageException(e); - } - }, - Function.identity(), - messageHandlingExecutor); + bytes -> new String(bytes, Charsets.UTF_8), + name -> { + try { + return toByteArray(getApplicationInputStream(name)); + } catch (IOException e) { + throw new StorageException(e); + } + }, + Function.identity(), + messageHandlingExecutor); // FIXME: Consider consolidating into a single map. @@ -161,6 +174,7 @@ public class GossipApplicationStore extends ApplicationArchive .withTimestampProvider((k, v) -> clockService.getTimestamp()) .build(); + coreAppId = getId(CoreService.CORE_APP_NAME); log.info("Started"); } @@ -169,20 +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())) { - 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 @@ -200,7 +228,6 @@ public class GossipApplicationStore extends ApplicationArchive public void setDelegate(ApplicationStoreDelegate delegate) { super.setDelegate(delegate); loadFromDisk(); -// executor.schedule(this::pruneUninstalledApps, LOAD_TIMEOUT_MS, MILLISECONDS); } @Override @@ -229,7 +256,15 @@ public class GossipApplicationStore extends ApplicationArchive @Override public Application create(InputStream appDescStream) { ApplicationDescription appDesc = saveApplication(appDescStream); - return create(appDesc, true); + if (hasPrerequisites(appDesc)) { + return create(appDesc, true); + } + throw new ApplicationException("Missing dependencies for app " + appDesc.name()); + } + + private boolean hasPrerequisites(ApplicationDescription app) { + return !app.requiredApps().stream().map(n -> getId(n)) + .anyMatch(id -> id == null || getApplication(id) == null); } private Application create(ApplicationDescription appDesc, boolean updateTime) { @@ -246,36 +281,80 @@ public class GossipApplicationStore extends ApplicationArchive public void remove(ApplicationId appId) { Application app = apps.get(appId); if (app != null) { + uninstallDependentApps(app); apps.remove(appId); states.remove(app); permissions.remove(app); } } + // Uninstalls all apps that depend on the given app. + private void uninstallDependentApps(Application app) { + getApplications().stream() + .filter(a -> a.requiredApps().contains(app.id().name())) + .forEach(a -> remove(a.id())); + } + @Override public void activate(ApplicationId appId) { + activate(appId, coreAppId); + } + + private void activate(ApplicationId appId, ApplicationId forAppId) { + requiredBy.put(appId, forAppId); activate(appId, true); } + private void activate(ApplicationId appId, boolean updateTime) { Application app = apps.get(appId); if (app != null) { if (updateTime) { updateTime(appId.name()); } + activateRequiredApps(app); states.put(app, ACTIVATED); } } + // Activates all apps required by this application. + private void activateRequiredApps(Application app) { + app.requiredApps().stream().map(this::getId).forEach(id -> activate(id, app.id())); + } + @Override public void deactivate(ApplicationId appId) { - Application app = apps.get(appId); - if (app != null) { - updateTime(appId.name()); - states.put(app, DEACTIVATED); + deactivateDependentApps(getApplication(appId)); + deactivate(appId, coreAppId); + } + + private void deactivate(ApplicationId appId, ApplicationId forAppId) { + requiredBy.remove(appId, forAppId); + if (requiredBy.get(appId).isEmpty()) { + Application app = apps.get(appId); + if (app != null) { + updateTime(appId.name()); + states.put(app, DEACTIVATED); + deactivateRequiredApps(app); + } } } + // Deactivates all apps that require this application. + private void deactivateDependentApps(Application app) { + getApplications().stream() + .filter(a -> states.get(a) == ACTIVATED) + .filter(a -> a.requiredApps().contains(app.id().name())) + .forEach(a -> deactivate(a.id())); + } + + // Deactivates all apps required by this application. + private void deactivateRequiredApps(Application app) { + app.requiredApps().stream().map(this::getId).map(this::getApplication) + .filter(a -> states.get(a) == ACTIVATED) + .forEach(a -> deactivate(a.id(), app.id())); + } + @Override public Set<Permission> getPermissions(ApplicationId appId) { Application app = apps.get(appId); @@ -424,6 +503,7 @@ public class GossipApplicationStore extends ApplicationArchive ApplicationId appId = idStore.registerApplication(appDesc.name()); return new DefaultApplication(appId, appDesc.version(), appDesc.description(), appDesc.origin(), appDesc.role(), appDesc.permissions(), - appDesc.featuresRepo(), appDesc.features()); + appDesc.featuresRepo(), appDesc.features(), + appDesc.requiredApps()); } } 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 9f6c4130..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; @@ -55,6 +56,11 @@ public class StaticClusterMetadataStore implements ClusterMetadataStore { private final Logger log = getLogger(getClass()); + + 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; private final File metadataFile = new File(CLUSTER_METADATA_FILE); @@ -194,28 +200,59 @@ public class StaticClusterMetadataStore private static String getSiteLocalAddress() { + + /* + * If the IP ONOS should use is set via the environment variable we will assume it is valid and should be used. + * Setting the IP address takes presidence over setting the interface via the environment. + */ + String useOnosIp = System.getenv(ONOS_IP); + if (useOnosIp != null) { + return useOnosIp; + } + + // Read environment variables for IP interface information or set to default + String useOnosInterface = System.getenv(ONOS_INTERFACE); + if (useOnosInterface == null) { + 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("eth0")); + IpAddress ip = ipLookup.apply(NetworkInterface.getByName(useOnosInterface)); if (ip != null) { 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(); } -}
\ No newline at end of file +} 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 23c81869..d61d7dcf 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 @@ -47,7 +47,7 @@ public class NettyMessagingManager extends NettyMessaging { @Activate public void activate() throws Exception { ControllerNode localNode = clusterMetadataService.getLocalNode(); - getTLSParameters(); + getTlsParameters(); super.start(new Endpoint(localNode.ip(), localNode.tcpPort())); log.info("Started"); } @@ -58,29 +58,29 @@ public class NettyMessagingManager extends NettyMessaging { log.info("Stopped"); } - private void getTLSParameters() { + private void getTlsParameters() { String tempString = System.getProperty("enableNettyTLS"); - enableNettyTLS = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString); - log.info("enableNettyTLS = {}", enableNettyTLS); - if (enableNettyTLS) { + enableNettyTls = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString); + log.info("enableNettyTLS = {}", enableNettyTls); + if (enableNettyTls) { ksLocation = System.getProperty("javax.net.ssl.keyStore"); if (Strings.isNullOrEmpty(ksLocation)) { - enableNettyTLS = TLS_DISABLED; + enableNettyTls = TLS_DISABLED; return; } tsLocation = System.getProperty("javax.net.ssl.trustStore"); if (Strings.isNullOrEmpty(tsLocation)) { - enableNettyTLS = TLS_DISABLED; + enableNettyTls = TLS_DISABLED; return; } ksPwd = System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(); if (MIN_KS_LENGTH > ksPwd.length) { - enableNettyTLS = TLS_DISABLED; + enableNettyTls = TLS_DISABLED; return; } tsPwd = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray(); if (MIN_KS_LENGTH > tsPwd.length) { - enableNettyTLS = TLS_DISABLED; + enableNettyTls = TLS_DISABLED; return; } } 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/device/impl/GossipDeviceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java index 687762e0..a9a9098e 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 @@ -986,6 +986,10 @@ public class GossipDeviceStore // accept removal request if given timestamp is newer than // the latest Timestamp from Primary provider DeviceDescriptions primDescs = getPrimaryDescriptions(descs); + if (primDescs == null) { + return null; + } + Timestamp lastTimestamp = primDescs.getLatestTimestamp(); if (timestamp.compareTo(lastTimestamp) <= 0) { // outdated event ignore @@ -1036,7 +1040,7 @@ public class GossipDeviceStore checkArgument(!providerDescs.isEmpty(), "No device descriptions supplied"); - ProviderId primary = pickPrimaryPID(providerDescs); + ProviderId primary = pickPrimaryPid(providerDescs); DeviceDescriptions desc = providerDescs.get(primary); @@ -1099,7 +1103,7 @@ public class GossipDeviceStore private Port composePort(Device device, PortNumber number, Map<ProviderId, DeviceDescriptions> descsMap) { - ProviderId primary = pickPrimaryPID(descsMap); + ProviderId primary = pickPrimaryPid(descsMap); DeviceDescriptions primDescs = descsMap.get(primary); // if no primary, assume not enabled boolean isEnabled = false; @@ -1145,7 +1149,7 @@ public class GossipDeviceStore /** * @return primary ProviderID, or randomly chosen one if none exists */ - private ProviderId pickPrimaryPID( + private ProviderId pickPrimaryPid( Map<ProviderId, DeviceDescriptions> providerDescs) { ProviderId fallBackPrimary = null; for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) { @@ -1161,7 +1165,7 @@ public class GossipDeviceStore private DeviceDescriptions getPrimaryDescriptions( Map<ProviderId, DeviceDescriptions> providerDescs) { - ProviderId pid = pickPrimaryPID(providerDescs); + ProviderId pid = pickPrimaryPid(providerDescs); return providerDescs.get(pid); } 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/flow/impl/NewDistributedFlowRuleStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/NewDistributedFlowRuleStore.java index 8cd63e7d..1695e5ff 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/NewDistributedFlowRuleStore.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/NewDistributedFlowRuleStore.java @@ -59,6 +59,7 @@ import org.onosproject.net.flow.FlowRuleStore; import org.onosproject.net.flow.FlowRuleStoreDelegate; import org.onosproject.net.flow.StoredFlowEntry; import org.onosproject.net.flow.TableStatisticsEntry; +import org.onosproject.persistence.PersistenceService; import org.onosproject.store.AbstractStore; import org.onosproject.store.cluster.messaging.ClusterCommunicationService; import org.onosproject.store.cluster.messaging.ClusterMessage; @@ -74,6 +75,7 @@ import org.onosproject.store.serializers.custom.DistributedStoreSerializers; 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.StorageService; import org.onosproject.store.service.WallClockTimestamp; import org.osgi.service.component.ComponentContext; @@ -113,6 +115,7 @@ public class NewDistributedFlowRuleStore private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 8; private static final boolean DEFAULT_BACKUP_ENABLED = true; + private static final boolean DEFAULT_PERSISTENCE_ENABLED = false; private static final int DEFAULT_BACKUP_PERIOD_MILLIS = 2000; private static final long FLOW_RULE_STORE_TIMEOUT_MILLIS = 5000; // number of devices whose flow entries will be backed up in one communication round @@ -129,6 +132,9 @@ public class NewDistributedFlowRuleStore @Property(name = "backupPeriod", intValue = DEFAULT_BACKUP_PERIOD_MILLIS, label = "Delay in ms between successive backup runs") private int backupPeriod = DEFAULT_BACKUP_PERIOD_MILLIS; + @Property(name = "persistenceEnabled", boolValue = false, + label = "Indicates whether or not changes in the flow table should be persisted to disk.") + private boolean persistenceEnabled = DEFAULT_PERSISTENCE_ENABLED; private InternalFlowTable flowTable = new InternalFlowTable(); @@ -153,6 +159,9 @@ public class NewDistributedFlowRuleStore @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected MastershipService mastershipService; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PersistenceService persistenceService; + private Map<Long, NodeId> pendingResponses = Maps.newConcurrentMap(); private ExecutorService messageHandlingExecutor; @@ -716,7 +725,25 @@ public class NewDistributedFlowRuleStore * @return Map representing Flow Table of given device. */ private Map<FlowId, Set<StoredFlowEntry>> getFlowTable(DeviceId deviceId) { - return flowEntries.computeIfAbsent(deviceId, id -> Maps.newConcurrentMap()); + if (persistenceEnabled) { + return flowEntries.computeIfAbsent(deviceId, id -> persistenceService + .<FlowId, Set<StoredFlowEntry>>persistentMapBuilder() + .withName("FlowTable:" + deviceId.toString()) + .withSerializer(new Serializer() { + @Override + public <T> byte[] encode(T object) { + return SERIALIZER.encode(object); + } + + @Override + public <T> T decode(byte[] bytes) { + return SERIALIZER.decode(bytes); + } + }) + .build()); + } else { + return flowEntries.computeIfAbsent(deviceId, id -> Maps.newConcurrentMap()); + } } private Set<StoredFlowEntry> getFlowEntriesInternal(DeviceId deviceId, FlowId flowId) { 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 f9c96891..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,8 +19,8 @@ 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_REMOVED; 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; import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE; @@ -28,9 +28,10 @@ import static org.slf4j.LoggerFactory.getLogger; import java.util.Collection; import java.util.HashSet; +import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -56,7 +57,6 @@ import org.onosproject.net.host.HostDescription; import org.onosproject.net.host.HostEvent; import org.onosproject.net.host.HostStore; import org.onosproject.net.host.HostStoreDelegate; -import org.onosproject.net.host.HostEvent.Type; import org.onosproject.net.provider.ProviderId; import org.onosproject.store.AbstractStore; import org.onosproject.store.serializers.KryoNamespaces; @@ -67,10 +67,7 @@ import org.onosproject.store.service.LogicalClockService; import org.onosproject.store.service.StorageService; import org.slf4j.Logger; -import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimaps; -import com.google.common.collect.SetMultimap; import com.google.common.collect.Sets; /** @@ -90,13 +87,11 @@ public class ECHostStore @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected LogicalClockService clockService; - // Hosts tracked by their location - private final SetMultimap<ConnectPoint, Host> locations = - Multimaps.synchronizedSetMultimap( - HashMultimap.<ConnectPoint, Host>create()); - private EventuallyConsistentMap<HostId, DefaultHost> hosts; + private final ConcurrentHashMap<HostId, DefaultHost> prevHosts = + new ConcurrentHashMap<>(); + private EventuallyConsistentMapListener<HostId, DefaultHost> hostLocationTracker = new HostLocationTracker(); @@ -120,11 +115,12 @@ public class ECHostStore public void deactivate() { hosts.removeListener(hostLocationTracker); hosts.destroy(); - locations.clear(); + prevHosts.clear(); log.info("Stopped"); } + // TODO No longer need to return HostEvent @Override public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId, @@ -133,18 +129,7 @@ public class ECHostStore // TODO: We need a way to detect conflicting changes and abort update. // (BOC) Compute might do this for us. - final AtomicReference<Type> eventType = new AtomicReference<>(); - final AtomicReference<DefaultHost> oldHost = new AtomicReference<>(); - DefaultHost host = hosts.compute(hostId, (id, existingHost) -> { - if (existingHost != null) { - oldHost.set(existingHost); - checkState(Objects.equals(hostDescription.hwAddress(), existingHost.mac()), - "Existing and new MAC addresses differ."); - checkState(Objects.equals(hostDescription.vlan(), existingHost.vlan()), - "Existing and new VLANs differ."); - } - - // TODO do we ever want the existing location? + hosts.compute(hostId, (id, existingHost) -> { HostLocation location = hostDescription.location(); final Set<IpAddress> addresses; @@ -163,15 +148,6 @@ public class ECHostStore annotations = hostDescription.annotations(); } - if (existingHost == null) { - eventType.set(HOST_ADDED); - } else if (!Objects.equals(existingHost.location(), hostDescription.location())) { - eventType.set(HOST_MOVED); - } else if (!existingHost.ipAddresses().containsAll(hostDescription.ipAddress()) || - !hostDescription.annotations().keys().isEmpty()) { - eventType.set(HOST_UPDATED); - } // else, eventType == null; this means we don't send an event - return new DefaultHost(providerId, hostId, hostDescription.hwAddress(), @@ -181,24 +157,20 @@ public class ECHostStore annotations); }); - if (oldHost.get() != null) { - DefaultHost old = oldHost.get(); - locations.remove(old.location(), old); - } - locations.put(host.location(), host); - - return eventType.get() != null ? new HostEvent(eventType.get(), host) : null; + return null; } + // TODO No longer need to return HostEvent @Override public HostEvent removeHost(HostId hostId) { - Host host = hosts.remove(hostId); - return host != null ? new HostEvent(HOST_REMOVED, host) : null; + hosts.remove(hostId); + return null; } + // TODO No longer need to return HostEvent @Override public HostEvent removeIp(HostId hostId, IpAddress ipAddress) { - DefaultHost host = hosts.compute(hostId, (id, existingHost) -> { + hosts.compute(hostId, (id, existingHost) -> { if (existingHost != null) { checkState(Objects.equals(hostId.mac(), existingHost.mac()), "Existing and new MAC addresses differ."); @@ -222,7 +194,7 @@ public class ECHostStore } return null; }); - return host != null ? new HostEvent(HOST_UPDATED, host) : null; + return null; } @Override @@ -257,22 +229,19 @@ public class ECHostStore @Override public Set<Host> getConnectedHosts(ConnectPoint connectPoint) { - synchronized (locations) { - return ImmutableSet.copyOf(locations.get(connectPoint)); - } + Set<Host> filtered = hosts.entrySet().stream() + .filter(entry -> entry.getValue().location().equals(connectPoint)) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); + return ImmutableSet.copyOf(filtered); } @Override public Set<Host> getConnectedHosts(DeviceId deviceId) { - Set<Host> filtered; - synchronized (locations) { - filtered = locations - .entries() - .stream() - .filter(entry -> entry.getKey().deviceId().equals(deviceId)) - .map(entry -> entry.getValue()) - .collect(Collectors.toSet()); - } + Set<Host> filtered = hosts.entrySet().stream() + .filter(entry -> entry.getValue().location().deviceId().equals(deviceId)) + .map(Map.Entry::getValue) + .collect(Collectors.toSet()); return ImmutableSet.copyOf(filtered); } @@ -285,13 +254,18 @@ public class ECHostStore public void event(EventuallyConsistentMapEvent<HostId, DefaultHost> event) { DefaultHost host = checkNotNull(event.value()); if (event.type() == PUT) { - boolean isNew = locations.put(host.location(), host); - notifyDelegate(new HostEvent(isNew ? HOST_ADDED : HOST_UPDATED, host)); + Host prevHost = prevHosts.put(host.id(), host); + if (prevHost == null) { + notifyDelegate(new HostEvent(HOST_ADDED, 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.location(), host)) { + 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/impl/LogicalTimestamp.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/LogicalTimestamp.java index 9382960f..dfee9980 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/LogicalTimestamp.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/impl/LogicalTimestamp.java @@ -50,7 +50,7 @@ public class LogicalTimestamp implements Timestamp { @Override public int hashCode() { - return Objects.hash(value); + return Long.hashCode(value); } @Override diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java index 885361f0..f6cd198f 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/intent/impl/PartitionId.java @@ -56,7 +56,7 @@ public class PartitionId { @Override public int hashCode() { - return Objects.hash(id); + return id; } @Override 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 687576c3..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 @@ -16,20 +16,23 @@ package org.onosproject.store.newresource.impl; import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableList; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onosproject.net.newresource.ResourceConsumer; +import org.onosproject.net.newresource.ResourceEvent; import org.onosproject.net.newresource.ResourcePath; import org.onosproject.net.newresource.ResourceStore; +import org.onosproject.net.newresource.ResourceStoreDelegate; +import org.onosproject.store.AbstractStore; import org.onosproject.store.serializers.KryoNamespaces; import org.onosproject.store.service.ConsistentMap; import org.onosproject.store.service.Serializer; import org.onosproject.store.service.StorageService; import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionException; import org.onosproject.store.service.TransactionalMap; import org.onosproject.store.service.Versioned; import org.slf4j.Logger; @@ -48,6 +51,7 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static org.onosproject.net.newresource.ResourceEvent.Type.*; /** * Implementation of ResourceStore using TransactionalMap. @@ -55,7 +59,8 @@ import static com.google.common.base.Preconditions.checkNotNull; @Component(immediate = true) @Service @Beta -public class ConsistentResourceStore implements ResourceStore { +public class ConsistentResourceStore extends AbstractStore<ResourceEvent, ResourceStoreDelegate> + implements ResourceStore { private static final Logger log = LoggerFactory.getLogger(ConsistentResourceStore.class); private static final String CONSUMER_MAP = "onos-resource-consumers"; @@ -79,6 +84,8 @@ public class ConsistentResourceStore implements ResourceStore { .withName(CHILD_MAP) .withSerializer(SERIALIZER) .build(); + + childMap.put(ResourcePath.ROOT, ImmutableList.of()); } @Override @@ -100,29 +107,32 @@ public class ConsistentResourceStore implements ResourceStore { TransactionContext tx = service.transactionContextBuilder().build(); tx.begin(); - try { - TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = - tx.getTransactionalMap(CHILD_MAP, SERIALIZER); + TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = + tx.getTransactionalMap(CHILD_MAP, SERIALIZER); - Map<ResourcePath, List<ResourcePath>> resourceMap = resources.stream() - .filter(x -> x.parent().isPresent()) - .collect(Collectors.groupingBy(x -> x.parent().get())); + Map<ResourcePath, List<ResourcePath>> resourceMap = resources.stream() + .filter(x -> x.parent().isPresent()) + .collect(Collectors.groupingBy(x -> x.parent().get())); - for (Map.Entry<ResourcePath, List<ResourcePath>> entry: resourceMap.entrySet()) { - if (!isRegistered(childTxMap, entry.getKey())) { - return abortTransaction(tx); - } + for (Map.Entry<ResourcePath, List<ResourcePath>> entry: resourceMap.entrySet()) { + if (!isRegistered(childTxMap, entry.getKey())) { + return abortTransaction(tx); + } - if (!appendValues(childTxMap, entry.getKey(), entry.getValue())) { - return abortTransaction(tx); - } + if (!appendValues(childTxMap, entry.getKey(), entry.getValue())) { + return abortTransaction(tx); } + } - return commitTransaction(tx); - } catch (TransactionException e) { - log.error("Exception thrown, abort the transaction", e); - return abortTransaction(tx); + boolean success = tx.commit(); + if (success) { + List<ResourceEvent> events = resources.stream() + .filter(x -> x.parent().isPresent()) + .map(x -> new ResourceEvent(RESOURCE_ADDED, x)) + .collect(Collectors.toList()); + notifyDelegate(events); } + return success; } @Override @@ -132,33 +142,36 @@ public class ConsistentResourceStore implements ResourceStore { TransactionContext tx = service.transactionContextBuilder().build(); tx.begin(); - try { - TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = - tx.getTransactionalMap(CHILD_MAP, SERIALIZER); - TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = - tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); + TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = + tx.getTransactionalMap(CHILD_MAP, SERIALIZER); + TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = + tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); - Map<ResourcePath, List<ResourcePath>> resourceMap = resources.stream() - .filter(x -> x.parent().isPresent()) - .collect(Collectors.groupingBy(x -> x.parent().get())); - - // even if one of the resources is allocated to a consumer, - // all unregistrations are regarded as failure - for (Map.Entry<ResourcePath, List<ResourcePath>> entry: resourceMap.entrySet()) { - if (entry.getValue().stream().anyMatch(x -> consumerTxMap.get(x) != null)) { - return abortTransaction(tx); - } - - if (!removeValues(childTxMap, entry.getKey(), entry.getValue())) { - return abortTransaction(tx); - } + Map<ResourcePath, List<ResourcePath>> resourceMap = resources.stream() + .filter(x -> x.parent().isPresent()) + .collect(Collectors.groupingBy(x -> x.parent().get())); + + // even if one of the resources is allocated to a consumer, + // all unregistrations are regarded as failure + for (Map.Entry<ResourcePath, List<ResourcePath>> entry: resourceMap.entrySet()) { + if (entry.getValue().stream().anyMatch(x -> consumerTxMap.get(x) != null)) { + return abortTransaction(tx); } - return commitTransaction(tx); - } catch (TransactionException e) { - log.error("Exception thrown, abort the transaction", e); - return abortTransaction(tx); + if (!removeValues(childTxMap, entry.getKey(), entry.getValue())) { + return abortTransaction(tx); + } + } + + boolean success = tx.commit(); + if (success) { + List<ResourceEvent> events = resources.stream() + .filter(x -> x.parent().isPresent()) + .map(x -> new ResourceEvent(RESOURCE_REMOVED, x)) + .collect(Collectors.toList()); + notifyDelegate(events); } + return success; } @Override @@ -169,28 +182,23 @@ public class ConsistentResourceStore implements ResourceStore { TransactionContext tx = service.transactionContextBuilder().build(); tx.begin(); - try { - TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = - tx.getTransactionalMap(CHILD_MAP, SERIALIZER); - TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = - tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); - - for (ResourcePath resource: resources) { - if (!isRegistered(childTxMap, resource)) { - return abortTransaction(tx); - } - - ResourceConsumer oldValue = consumerTxMap.put(resource, consumer); - if (oldValue != null) { - return abortTransaction(tx); - } + TransactionalMap<ResourcePath, List<ResourcePath>> childTxMap = + tx.getTransactionalMap(CHILD_MAP, SERIALIZER); + TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = + tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); + + for (ResourcePath resource: resources) { + if (!isRegistered(childTxMap, resource)) { + return abortTransaction(tx); } - return commitTransaction(tx); - } catch (TransactionException e) { - log.error("Exception thrown, abort the transaction", e); - return abortTransaction(tx); + ResourceConsumer oldValue = consumerTxMap.put(resource, consumer); + if (oldValue != null) { + return abortTransaction(tx); + } } + + return tx.commit(); } @Override @@ -202,28 +210,23 @@ public class ConsistentResourceStore implements ResourceStore { TransactionContext tx = service.transactionContextBuilder().build(); tx.begin(); - try { - TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = - tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); - Iterator<ResourcePath> resourceIte = resources.iterator(); - Iterator<ResourceConsumer> consumerIte = consumers.iterator(); - - while (resourceIte.hasNext() && consumerIte.hasNext()) { - ResourcePath resource = resourceIte.next(); - ResourceConsumer consumer = consumerIte.next(); - - // if this single release fails (because the resource is allocated to another consumer, - // the whole release fails - if (!consumerTxMap.remove(resource, consumer)) { - return abortTransaction(tx); - } - } + TransactionalMap<ResourcePath, ResourceConsumer> consumerTxMap = + tx.getTransactionalMap(CONSUMER_MAP, SERIALIZER); + Iterator<ResourcePath> resourceIte = resources.iterator(); + Iterator<ResourceConsumer> consumerIte = consumers.iterator(); + + while (resourceIte.hasNext() && consumerIte.hasNext()) { + ResourcePath resource = resourceIte.next(); + ResourceConsumer consumer = consumerIte.next(); - return commitTransaction(tx); - } catch (TransactionException e) { - log.error("Exception thrown, abort the transaction", e); - return abortTransaction(tx); + // if this single release fails (because the resource is allocated to another consumer, + // the whole release fails + if (!consumerTxMap.remove(resource, consumer)) { + return abortTransaction(tx); + } } + + return tx.commit(); } @Override @@ -261,7 +264,7 @@ public class ConsistentResourceStore implements ResourceStore { } return children.value().stream() - .filter(x -> x.lastComponent().getClass().equals(cls)) + .filter(x -> x.last().getClass().equals(cls)) .filter(consumerMap::containsKey) .collect(Collectors.toList()); } @@ -278,17 +281,6 @@ public class ConsistentResourceStore implements ResourceStore { } /** - * Commit the transaction. - * - * @param tx transaction context - * @return always true - */ - private boolean commitTransaction(TransactionContext tx) { - tx.commit(); - return true; - } - - /** * Appends the values to the existing values associated with the specified key. * If the map already has all the given values, appending will not happen. * @@ -300,9 +292,9 @@ public class ConsistentResourceStore implements ResourceStore { * @return true if the operation succeeds, false otherwise. */ private <K, V> boolean appendValues(TransactionalMap<K, List<V>> map, K key, List<V> values) { - List<V> oldValues = map.get(key); + List<V> oldValues = map.putIfAbsent(key, new ArrayList<>(values)); if (oldValues == null) { - return map.replace(key, oldValues, new ArrayList<>(values)); + return true; } LinkedHashSet<V> oldSet = new LinkedHashSet<>(oldValues); @@ -329,7 +321,8 @@ public class ConsistentResourceStore implements ResourceStore { private <K, V> boolean removeValues(TransactionalMap<K, List<V>> map, K key, List<V> values) { List<V> oldValues = map.get(key); if (oldValues == null) { - return map.replace(key, oldValues, new ArrayList<>()); + map.put(key, new ArrayList<>()); + return true; } LinkedHashSet<V> oldSet = new LinkedHashSet<>(oldValues); @@ -351,7 +344,7 @@ public class ConsistentResourceStore implements ResourceStore { */ 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/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java index c332ada5..351c7a5f 100644 --- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentLinkResourceStore.java @@ -59,7 +59,6 @@ import org.onosproject.store.service.ConsistentMap; import org.onosproject.store.service.Serializer; import org.onosproject.store.service.StorageService; import org.onosproject.store.service.TransactionContext; -import org.onosproject.store.service.TransactionException; import org.onosproject.store.service.TransactionalMap; import org.onosproject.store.service.Versioned; @@ -73,7 +72,10 @@ import static org.onosproject.net.AnnotationKeys.BANDWIDTH; /** * Store that manages link resources using Copycat-backed TransactionalMaps. + * + * @deprecated in Emu Release */ +@Deprecated @Component(immediate = true, enabled = true) @Service public class ConsistentLinkResourceStore extends @@ -294,7 +296,7 @@ public class ConsistentLinkResourceStore extends intentAllocs.put(allocations.intentId(), allocations); allocations.links().forEach(link -> allocateLinkResource(tx, link, allocations)); tx.commit(); - } catch (TransactionException | ResourceAllocationException e) { + } catch (ResourceAllocationException e) { log.error("Exception thrown, rolling back", e); tx.abort(); } catch (Exception e) { @@ -407,12 +409,8 @@ public class ConsistentLinkResourceStore extends after.remove(allocations); linkAllocs.replace(linkId, before, after); }); - tx.commit(); - success = true; - } catch (TransactionException e) { - log.debug("Transaction failed, retrying", e); - tx.abort(); - } catch (Exception e) { + success = tx.commit(); + } catch (Exception e) { log.error("Exception thrown during releaseResource {}", allocations, e); tx.abort(); throw e; diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java index 3a168936..5cbf360a 100644 --- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java +++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/device/impl/GossipDeviceStoreTest.java @@ -232,7 +232,7 @@ public class GossipDeviceStoreTest { if (expected == actual) { return; } - assertEquals(expected.deviceURI(), actual.deviceURI()); + assertEquals(expected.deviceUri(), actual.deviceUri()); assertEquals(expected.hwVersion(), actual.hwVersion()); assertEquals(expected.manufacturer(), actual.manufacturer()); assertEquals(expected.serialNumber(), actual.serialNumber()); @@ -247,7 +247,7 @@ public class GossipDeviceStoreTest { if (expected == actual) { return; } - assertEquals(expected.deviceURI(), actual.deviceURI()); + assertEquals(expected.deviceUri(), actual.deviceUri()); assertEquals(expected.hwVersion(), actual.hwVersion()); assertEquals(expected.manufacturer(), actual.manufacturer()); assertEquals(expected.serialNumber(), actual.serialNumber()); 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/persistence/pom.xml b/framework/src/onos/core/store/persistence/pom.xml index 555de11a..5692c531 100644 --- a/framework/src/onos/core/store/persistence/pom.xml +++ b/framework/src/onos/core/store/persistence/pom.xml @@ -50,7 +50,7 @@ <groupId>org.onosproject</groupId> <artifactId>onos-api</artifactId> </dependency>--> - <dependency> + <dependency> <groupId>org.onosproject</groupId> <artifactId>onos-api</artifactId> <classifier>tests</classifier> diff --git a/framework/src/onos/core/store/pom.xml b/framework/src/onos/core/store/pom.xml index 219ae5d0..94c077a4 100644 --- a/framework/src/onos/core/store/pom.xml +++ b/framework/src/onos/core/store/pom.xml @@ -34,7 +34,7 @@ <modules> <module>dist</module> <module>persistence</module> - <module>serializers</module> + <module>serializers</module> </modules> <dependencies> 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 0312bafd..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, @@ -438,7 +440,7 @@ public final class KryoNamespaces { DefaultTableStatisticsEntry.class ) .register(new DefaultApplicationIdSerializer(), DefaultApplicationId.class) - .register(new URISerializer(), URI.class) + .register(new UriSerializer(), URI.class) .register(new NodeIdSerializer(), NodeId.class) .register(new ProviderIdSerializer(), ProviderId.class) .register(new DeviceIdSerializer(), DeviceId.class) diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/URISerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/UriSerializer.java index 43969666..1d146a55 100644 --- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/URISerializer.java +++ b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/UriSerializer.java @@ -15,22 +15,22 @@ */ package org.onosproject.store.serializers; -import java.net.URI; - import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; +import java.net.URI; + /** * Serializer for {@link URI}. */ -public class URISerializer extends Serializer<URI> { +public class UriSerializer extends Serializer<URI> { /** * Creates {@link URI} serializer instance. */ - public URISerializer() { + public UriSerializer() { super(false); } 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))); } |