diff options
Diffstat (limited to 'framework/src/onos/core/net')
32 files changed, 1587 insertions, 215 deletions
diff --git a/framework/src/onos/core/net/pom.xml b/framework/src/onos/core/net/pom.xml index 9ea00070..c5d31263 100644 --- a/framework/src/onos/core/net/pom.xml +++ b/framework/src/onos/core/net/pom.xml @@ -52,6 +52,20 @@ <dependency> <groupId>org.onosproject</groupId> + <version>${project.version}</version> + <artifactId>onos-cli</artifactId> + </dependency> + + <dependency> + <groupId>org.onosproject</groupId> + <artifactId>onos-cli</artifactId> + <version>${project.version}</version> + <classifier>tests</classifier> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.onosproject</groupId> <artifactId>onos-core-common</artifactId> <version>${project.version}</version> <classifier>tests</classifier> diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigLoader.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigLoader.java new file mode 100644 index 00000000..6678db27 --- /dev/null +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigLoader.java @@ -0,0 +1,74 @@ +/* + * 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.cfg.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +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.onosproject.cfg.ComponentConfigService; +import org.slf4j.Logger; + +import java.io.File; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Component responsible for automatically loading configuration file from + * configuration directory. + */ +@Component(immediate = true) +public class ComponentConfigLoader { + + private static final String CFG_JSON = "../config/component-cfg.json"; + static File cfgFile = new File(CFG_JSON); + + private final Logger log = getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected ComponentConfigService configService; + + private ObjectNode root; + + @Activate + protected void activate() { + this.loadConfigs(); + log.info("Started"); + } + + // Loads the configurations for each component from the file in + // ../config/component-cfg.json, using the preSetProperty method. + private void loadConfigs() { + try { + if (cfgFile.exists()) { + root = (ObjectNode) new ObjectMapper().readTree(cfgFile); + root.fieldNames(). + forEachRemaining(component -> root.path(component).fieldNames() + .forEachRemaining(k -> configService + .preSetProperty(component, k, + root.path(component).path(k) + .asText()))); + log.info("Loaded initial component configuration from {}", cfgFile); + } + } catch (Exception e) { + log.warn("Unable to load initial component configuration from {}", + cfgFile, e); + } + } +} diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigManager.java index 1933ee55..b3b22c76 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cfg/impl/ComponentConfigManager.java @@ -61,6 +61,9 @@ public class ComponentConfigManager implements ComponentConfigService { private static final String COMPONENT_NULL = "Component name cannot be null"; private static final String PROPERTY_NULL = "Property name cannot be null"; + private static final String COMPONENT_MISSING = "Component %s is not registered"; + private static final String PROPERTY_MISSING = "Property %s does not exist for %s"; + //Symbolic constants for use with the accumulator private static final int MAX_ITEMS = 100; @@ -160,6 +163,22 @@ public class ComponentConfigManager implements ComponentConfigService { checkNotNull(componentName, COMPONENT_NULL); checkNotNull(name, PROPERTY_NULL); + + checkArgument(properties.containsKey(componentName), + COMPONENT_MISSING, componentName); + checkArgument(properties.get(componentName).containsKey(name), + PROPERTY_MISSING, name, componentName); + store.setProperty(componentName, name, value); + } + + @Override + public void preSetProperty(String componentName, String name, String value) { + + checkPermission(CONFIG_WRITE); + + checkNotNull(componentName, COMPONENT_NULL); + checkNotNull(name, PROPERTY_NULL); + store.setProperty(componentName, name, value); } @@ -169,6 +188,11 @@ public class ComponentConfigManager implements ComponentConfigService { checkNotNull(componentName, COMPONENT_NULL); checkNotNull(name, PROPERTY_NULL); + + checkArgument(properties.containsKey(componentName), + COMPONENT_MISSING, componentName); + checkArgument(properties.get(componentName).containsKey(name), + PROPERTY_MISSING, name, componentName); store.unsetProperty(componentName, name); } 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 8a441f61..f4d560a4 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,7 +24,6 @@ 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.onlab.util.Tools; import org.onosproject.cfg.ComponentConfigService; import org.onosproject.core.ApplicationId; import org.onosproject.core.ApplicationIdStore; @@ -38,6 +37,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Dictionary; import java.util.List; import java.util.Set; @@ -87,9 +90,15 @@ public class CoreManager implements CoreService { public void activate() { registerApplication(CORE_APP_NAME); cfgService.registerProperties(getClass()); - List<String> versionLines = Tools.slurp(VERSION_FILE); - if (versionLines != null && !versionLines.isEmpty()) { - version = Version.version(versionLines.get(0)); + try { + Path path = Paths.get(VERSION_FILE.getPath()); + List<String> versionLines = Files.readAllLines(path); + if (versionLines != null && !versionLines.isEmpty()) { + version = Version.version(versionLines.get(0)); + } + } catch (IOException e) { + // version file not found, using default + log.trace("Version file not found", e); } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigManager.java index 5cd96cab..db484eea 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigManager.java @@ -96,7 +96,7 @@ public class NetworkConfigManager configClasses.put(identifier(configFactory), configFactory.configClass()); SubjectFactory subjectFactory = configFactory.subjectFactory(); - subjectClasses.putIfAbsent(subjectFactory.subjectKey(), subjectFactory); + subjectClasses.putIfAbsent(subjectFactory.subjectClassKey(), subjectFactory); subjectClassKeys.putIfAbsent(subjectFactory.subjectClass(), subjectFactory); store.addConfigFactory(configFactory); @@ -145,8 +145,8 @@ public class NetworkConfigManager } @Override - public SubjectFactory getSubjectFactory(String subjectKey) { - return subjectClasses.get(subjectKey); + public SubjectFactory getSubjectFactory(String subjectClassKey) { + return subjectClasses.get(subjectClassKey); } @Override @@ -155,8 +155,8 @@ public class NetworkConfigManager } @Override - public Class<? extends Config> getConfigClass(String subjectKey, String configKey) { - return configClasses.get(new ConfigIdentifier(subjectKey, configKey)); + public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) { + return configClasses.get(new ConfigIdentifier(subjectClassKey, configKey)); } @Override @@ -255,7 +255,7 @@ public class NetworkConfigManager } private static ConfigIdentifier identifier(ConfigFactory factory) { - return new ConfigIdentifier(factory.subjectFactory().subjectKey(), factory.configKey()); + return new ConfigIdentifier(factory.subjectFactory().subjectClassKey(), factory.configKey()); } static final class ConfigIdentifier { 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 7900d185..fa90eb65 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 @@ -15,21 +15,21 @@ */ package org.onosproject.net.device.impl; -import static org.slf4j.LoggerFactory.getLogger; -import static com.google.common.base.Preconditions.checkNotNull; - -import org.onosproject.net.config.ConfigOperator; -import org.onosproject.net.config.basics.BasicDeviceConfig; import org.onosproject.net.AnnotationKeys; import org.onosproject.net.DefaultAnnotations; import org.onosproject.net.Device; import org.onosproject.net.SparseAnnotations; +import org.onosproject.net.config.ConfigOperator; +import org.onosproject.net.config.basics.BasicDeviceConfig; import org.onosproject.net.device.DefaultDeviceDescription; import org.onosproject.net.device.DeviceDescription; import org.slf4j.Logger; import java.util.Objects; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + /** * Implementations of merge policies for various sources of device configuration * information. This includes applications, provides, and network configurations. @@ -46,7 +46,7 @@ public final class BasicDeviceOperator implements ConfigOperator { * Generates a DeviceDescription containing fields from a DeviceDescription and * a DeviceConfig. * - * @param bdc the device config entity from network config + * @param bdc the device config entity from network config * @param descr a DeviceDescription * @return DeviceDescription based on both sources */ @@ -70,7 +70,7 @@ public final class BasicDeviceOperator implements ConfigOperator { * Generates an annotation from an existing annotation and DeviceConfig. * * @param bdc the device config entity from network config - * @param an the annotation + * @param an the annotation * @return annotation combining both sources */ public static SparseAnnotations combine(BasicDeviceConfig bdc, SparseAnnotations an) { @@ -93,6 +93,9 @@ public final class BasicDeviceOperator implements ConfigOperator { if (bdc.owner() != null) { newBuilder.set(AnnotationKeys.OWNER, bdc.owner()); } + if (bdc.managementAddress() != null) { + newBuilder.set(AnnotationKeys.MANAGEMENT_ADDRESS, bdc.managementAddress()); + } DefaultAnnotations newAnnotations = newBuilder.build(); return DefaultAnnotations.union(an, newAnnotations); } 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 b0b3abe2..e35dc0c5 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 @@ -15,8 +15,26 @@ */ package org.onosproject.net.device.impl; -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.Futures; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; +import static org.onlab.util.Tools.groupedThreads; +import static org.onosproject.net.MastershipRole.MASTER; +import static org.onosproject.net.MastershipRole.NONE; +import static org.onosproject.net.MastershipRole.STANDBY; +import static org.onosproject.security.AppGuard.checkPermission; +import static org.onosproject.security.AppPermission.Type.DEVICE_READ; +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -26,12 +44,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onosproject.cluster.ClusterService; import org.onosproject.cluster.NodeId; -import org.onosproject.net.provider.AbstractListenerProviderRegistry; -import org.onosproject.net.config.NetworkConfigEvent; -import org.onosproject.net.config.NetworkConfigListener; -import org.onosproject.net.config.NetworkConfigService; -import org.onosproject.net.config.basics.BasicDeviceConfig; -import org.onosproject.net.config.basics.OpticalPortConfig; import org.onosproject.mastership.MastershipEvent; import org.onosproject.mastership.MastershipListener; import org.onosproject.mastership.MastershipService; @@ -44,6 +56,11 @@ import org.onosproject.net.DeviceId; import org.onosproject.net.MastershipRole; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; +import org.onosproject.net.config.NetworkConfigEvent; +import org.onosproject.net.config.NetworkConfigListener; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.net.config.basics.BasicDeviceConfig; +import org.onosproject.net.config.basics.OpticalPortConfig; import org.onosproject.net.device.DefaultDeviceDescription; import org.onosproject.net.device.DefaultPortDescription; import org.onosproject.net.device.DeviceAdminService; @@ -58,27 +75,11 @@ import org.onosproject.net.device.DeviceStore; import org.onosproject.net.device.DeviceStoreDelegate; import org.onosproject.net.device.PortDescription; import org.onosproject.net.device.PortStatistics; +import org.onosproject.net.provider.AbstractListenerProviderRegistry; import org.onosproject.net.provider.AbstractProviderService; import org.slf4j.Logger; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import static com.google.common.base.Preconditions.checkNotNull; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.net.MastershipRole.*; -import static org.onosproject.security.AppGuard.checkPermission; -import static org.slf4j.LoggerFactory.getLogger; -import static org.onosproject.security.AppPermission.Type.*; +import com.google.common.util.concurrent.Futures; /** * Provides implementation of the device SB & NB APIs. @@ -347,11 +348,15 @@ public class DeviceManager log.info("Device {} disconnected from this node", deviceId); List<Port> ports = store.getPorts(deviceId); - List<PortDescription> descs = Lists.newArrayList(); - ports.forEach(port -> - descs.add(new DefaultPortDescription(port.number(), - false, port.type(), - port.portSpeed()))); + final Device device = getDevice(deviceId); + + List<PortDescription> descs = ports.stream().map( + port -> (!(Device.Type.ROADM.equals(device.type()))) ? + new DefaultPortDescription(port.number(), false, + port.type(), port.portSpeed()) : + OpticalPortOperator.descriptionOf(port, false) + ).collect(Collectors.toList()); + store.updatePorts(this.provider().id(), deviceId, descs); try { if (mastershipService.isLocalMaster(deviceId)) { @@ -430,6 +435,12 @@ public class DeviceManager portDescription); return; } + final Device device = getDevice(deviceId); + if ((Device.Type.ROADM.equals(device.type()))) { + Port port = getPort(deviceId, portDescription.portNumber()); + portDescription = OpticalPortOperator.descriptionOf(port, portDescription.isEnabled()); + } + portDescription = consolidate(deviceId, portDescription); final DeviceEvent event = store.updatePortStatus(this.provider().id(), deviceId, portDescription); diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java index b2fd02c7..8f2bda01 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java @@ -151,8 +151,25 @@ public final class OpticalPortOperator implements ConfigOperator { */ public static PortDescription descriptionOf(Port port) { checkNotNull(port, "Must supply non-null Port"); + final boolean isUp = port.isEnabled(); + return descriptionOfPort(port, isUp); + } + + /** + * Returns a description built from an existing port and reported status. + * + * @param port + * @param isEnabled + * @return a PortDescription based on the port + */ + static PortDescription descriptionOf(Port port, boolean isEnabled) { + checkNotNull(port, "Must supply non-null Port"); + final boolean isup = isEnabled; + return descriptionOfPort(port, isup); + } + + private static PortDescription descriptionOfPort(Port port, final boolean isup) { final PortNumber ptn = port.number(); - final boolean isup = port.isEnabled(); final SparseAnnotations an = (SparseAnnotations) port.annotations(); switch (port.type()) { case OMS: diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java index a1d046c5..5958d1f5 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java @@ -22,6 +22,7 @@ import com.google.common.collect.Lists; 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; @@ -58,6 +59,7 @@ import org.onosproject.net.flow.FlowRuleProviderService; import org.onosproject.net.flow.FlowRuleService; import org.onosproject.net.flow.FlowRuleStore; import org.onosproject.net.flow.FlowRuleStoreDelegate; +import org.onosproject.net.flow.TableStatisticsEntry; import org.onosproject.net.provider.AbstractProviderService; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; @@ -388,6 +390,16 @@ public class FlowRuleManager @Override public void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries) { + pushFlowMetricsInternal(deviceId, flowEntries, true); + } + + @Override + public void pushFlowMetricsWithoutFlowMissing(DeviceId deviceId, Iterable<FlowEntry> flowEntries) { + pushFlowMetricsInternal(deviceId, flowEntries, false); + } + + private void pushFlowMetricsInternal(DeviceId deviceId, Iterable<FlowEntry> flowEntries, + boolean useMissingFlow) { Map<FlowEntry, FlowEntry> storedRules = Maps.newHashMap(); store.getFlowEntries(deviceId).forEach(f -> storedRules.put(f, f)); @@ -415,17 +427,20 @@ public class FlowRuleManager continue; } } - for (FlowEntry rule : storedRules.keySet()) { - try { - // there are rules in the store that aren't on the switch - log.debug("Adding rule in store, but not on switch {}", rule); - flowMissing(rule); - } catch (Exception e) { - log.debug("Can't add missing flow rule {}", e.getMessage()); - continue; + + // DO NOT reinstall + if (useMissingFlow) { + for (FlowEntry rule : storedRules.keySet()) { + try { + // there are rules in the store that aren't on the switch + log.debug("Adding rule in store, but not on switch {}", rule); + flowMissing(rule); + } catch (Exception e) { + log.debug("Can't add missing flow rule {}", e.getMessage()); + continue; + } } } - } @Override @@ -435,6 +450,12 @@ public class FlowRuleManager operation )); } + + @Override + public void pushTableStatistics(DeviceId deviceId, + List<TableStatisticsEntry> tableStats) { + store.updateTableStatistics(deviceId, tableStats); + } } // Store delegate to re-post events emitted from the store. @@ -590,4 +611,10 @@ public class FlowRuleManager } } + + @Override + public Iterable<TableStatisticsEntry> getFlowTableStatistics(DeviceId deviceId) { + checkPermission(FLOWRULE_READ); + return store.getTableStatistics(deviceId); + } } 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 43f346b7..1473f33f 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 @@ -236,6 +236,16 @@ public class HostManager post(event); } } + + @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 delegate to re-post events emitted from the store. diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java index 44f8cbf0..4dc93a51 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java @@ -84,6 +84,7 @@ public class HostMonitor implements TimerTask { * @param hostManager host manager used to look up host information and * probe existing hosts * @param interfaceService interface service for interface information + * @param edgePortService edge port service */ public HostMonitor(PacketService packetService, HostManager hostManager, InterfaceService interfaceService, diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentCleanup.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentCleanup.java index d7fa3223..417627ad 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentCleanup.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentCleanup.java @@ -196,7 +196,7 @@ public class IntentCleanup implements Runnable, IntentListener { service.withdraw(intentData.intent()); break; default: - log.warn("Trying to resubmit pending intent {} in state {} with request {}", + log.warn("Failed to resubmit pending intent {} in state {} with request {}", intentData.key(), intentData.state(), intentData.request()); break; } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java index 4c828e77..baa3bf4d 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java @@ -256,15 +256,16 @@ public class IntentManager submit(intent); } - // If required, compile all currently failed intents. - for (Intent intent : getIntents()) { - IntentState state = getIntentState(intent.key()); - if ((compileAllFailed && RECOMPILE.contains(state)) - || intentAllowsPartialFailure(intent)) { - if (WITHDRAW.contains(state)) { - withdraw(intent); - } else { - submit(intent); + if (compileAllFailed) { + // If required, compile all currently failed intents. + for (Intent intent : getIntents()) { + IntentState state = getIntentState(intent.key()); + if (RECOMPILE.contains(state) || intentAllowsPartialFailure(intent)) { + if (WITHDRAW.contains(state)) { + withdraw(intent); + } else { + submit(intent); + } } } } 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 5710aced..5ebc812e 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 @@ -16,8 +16,8 @@ package org.onosproject.net.intent.impl; import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.SetMultimap; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -61,7 +61,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -91,8 +90,6 @@ public class ObjectiveTracker implements ObjectiveTrackerService { private final Logger log = getLogger(getClass()); - private final ConcurrentMap<Key, Intent> intents = Maps.newConcurrentMap(); - private final SetMultimap<LinkKey, Key> intentsByLink = //TODO this could be slow as a point of synchronization synchronizedSetMultimap(HashMultimap.<LinkKey, Key>create()); @@ -378,7 +375,12 @@ public class ObjectiveTracker implements ObjectiveTrackerService { } // TODO should we recompile on available==true? - delegate.triggerCompile(intentsByDevice.get(id), available); + + final ImmutableSet<Key> snapshot; + synchronized (intentsByDevice) { + snapshot = ImmutableSet.copyOf(intentsByDevice.get(id)); + } + delegate.triggerCompile(snapshot, available); } } @@ -415,9 +417,17 @@ public class ObjectiveTracker implements ObjectiveTrackerService { @Override public void event(HostEvent event) { HostId id = event.subject().id(); - HostEvent.Type type = event.type(); - boolean available = (type == HostEvent.Type.HOST_ADDED); - executorService.execute(new DeviceAvailabilityHandler(id, available)); + switch (event.type()) { + case HOST_ADDED: + case HOST_MOVED: + case HOST_REMOVED: + executorService.execute(new DeviceAvailabilityHandler(id, false)); + break; + case HOST_UPDATED: + default: + // DO NOTHING + break; + } } } 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 99f58df7..c6eb7c5a 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 @@ -15,10 +15,8 @@ */ package org.onosproject.net.intent.impl.compiler; -import com.google.common.collect.Sets; import org.apache.commons.lang3.tuple.Pair; import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Modified; import org.apache.felix.scr.annotations.Property; @@ -50,7 +48,10 @@ import org.onosproject.net.intent.IntentService; import org.onosproject.net.intent.OpticalCircuitIntent; import org.onosproject.net.intent.OpticalConnectivityIntent; import org.onosproject.net.intent.impl.IntentCompilationException; -import org.onosproject.net.resource.device.DeviceResourceService; +import org.onosproject.net.newresource.ResourceAllocation; +import org.onosproject.net.newresource.ResourcePath; +import org.onosproject.net.newresource.ResourceService; +import org.onosproject.net.resource.device.IntentSetMultimap; import org.onosproject.net.resource.link.LinkResourceAllocations; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; @@ -60,6 +61,7 @@ import java.util.Collections; import java.util.Dictionary; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; @@ -67,7 +69,8 @@ import static com.google.common.base.Preconditions.checkArgument; /** * An intent compiler for {@link org.onosproject.net.intent.OpticalCircuitIntent}. */ -@Component(immediate = true) +// For now, remove component designation until dependency on the new resource manager is available. +// @Component(immediate = true) public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircuitIntent> { private static final Logger log = LoggerFactory.getLogger(OpticalCircuitIntentCompiler.class); @@ -92,7 +95,10 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu protected DeviceService deviceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceResourceService deviceResourceService; + protected ResourceService resourceService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected IntentSetMultimap intentSetMultimap; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected IntentService intentService; @@ -153,7 +159,10 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu log.debug("Compiling optical circuit intent between {} and {}", src, dst); // Reserve OduClt ports - if (!deviceResourceService.requestPorts(Sets.newHashSet(srcPort, dstPort), intent)) { + ResourcePath srcPortPath = new ResourcePath(src.deviceId(), src.port()); + ResourcePath dstPortPath = new ResourcePath(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); } @@ -199,7 +208,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu circuitIntent = new FlowRuleIntent(appId, rules, intent.resources()); // Save circuit to connectivity intent mapping - deviceResourceService.requestMapping(connIntent.id(), intent.id()); + intentSetMultimap.allocateMapping(connIntent.id(), intent.id()); intents.add(circuitIntent); return intents; @@ -209,16 +218,15 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu * Checks if current allocations on given resource can satisfy request. * If the resource is null, return true. * - * @param request the intent making the request * @param resource the resource on which to map the intent * @return true if the resource can accept the request, false otherwise */ - private boolean isAvailable(Intent request, IntentId resource) { + private boolean isAvailable(IntentId resource) { if (resource == null) { return true; } - Set<IntentId> mapping = deviceResourceService.getMapping(resource); + Set<IntentId> mapping = intentSetMultimap.getMapping(resource); if (mapping == null) { return true; @@ -271,7 +279,7 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu continue; } - if (isAvailable(circuitIntent, connIntent.id())) { + if (isAvailable(connIntent.id())) { return connIntent; } } @@ -296,14 +304,19 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu return null; } - private OchPort findAvailableOchPort(ConnectPoint oduPort, OpticalCircuitIntent circuitIntent) { + private OchPort findAvailableOchPort(ConnectPoint oduPort) { // First see if the port mappings are constrained ConnectPoint ochCP = staticPort(oduPort); if (ochCP != null) { OchPort ochPort = (OchPort) deviceService.getPort(ochCP.deviceId(), ochCP.port()); - IntentId intentId = deviceResourceService.getAllocations(ochPort); - if (isAvailable(circuitIntent, intentId)) { + Optional<IntentId> intentId = + resourceService.getResourceAllocation(new ResourcePath(ochCP.deviceId(), ochCP.port())) + .map(ResourceAllocation::consumer) + .filter(x -> x instanceof IntentId) + .map(x -> (IntentId) x); + + if (isAvailable(intentId.orElse(null))) { return ochPort; } } @@ -316,8 +329,12 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu continue; } - IntentId intentId = deviceResourceService.getAllocations(port); - if (isAvailable(circuitIntent, intentId)) { + Optional<IntentId> intentId = + resourceService.getResourceAllocation(new ResourcePath(oduPort.deviceId(), port.number())) + .map(ResourceAllocation::consumer) + .filter(x -> x instanceof IntentId) + .map(x -> (IntentId) x); + if (isAvailable(intentId.orElse(null))) { return (OchPort) port; } } @@ -327,12 +344,12 @@ public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircu private Pair<OchPort, OchPort> findPorts(OpticalCircuitIntent intent) { - OchPort srcPort = findAvailableOchPort(intent.getSrc(), intent); + OchPort srcPort = findAvailableOchPort(intent.getSrc()); if (srcPort == null) { return null; } - OchPort dstPort = findAvailableOchPort(intent.getDst(), intent); + OchPort dstPort = findAvailableOchPort(intent.getDst()); if (dstPort == null) { return null; } 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 05a20f96..eb5b4af8 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java @@ -16,9 +16,7 @@ package org.onosproject.net.intent.impl.compiler; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; 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; @@ -40,9 +38,9 @@ import org.onosproject.net.intent.IntentExtensionService; import org.onosproject.net.intent.OpticalConnectivityIntent; import org.onosproject.net.intent.OpticalPathIntent; import org.onosproject.net.intent.impl.IntentCompilationException; -import org.onosproject.net.resource.ResourceAllocation; +import org.onosproject.net.newresource.ResourcePath; +import org.onosproject.net.newresource.ResourceService; import org.onosproject.net.resource.ResourceType; -import org.onosproject.net.resource.device.DeviceResourceService; import org.onosproject.net.resource.link.DefaultLinkResourceRequest; import org.onosproject.net.resource.link.LambdaResource; import org.onosproject.net.resource.link.LambdaResourceAllocation; @@ -57,13 +55,15 @@ import org.slf4j.LoggerFactory; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; /** * An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}. */ -@Component(immediate = true) +// For now, remove component designation until dependency on the new resource manager is available. +// @Component(immediate = true) public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> { protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class); @@ -78,10 +78,10 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical protected DeviceService deviceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkResourceService linkResourceService; + protected ResourceService resourceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceResourceService deviceResourceService; + protected LinkResourceService linkResourceService; @Activate public void activate() { @@ -108,7 +108,11 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical log.debug("Compiling optical connectivity intent between {} and {}", src, dst); // Reserve OCh ports - if (!deviceResourceService.requestPorts(ImmutableSet.of(srcPort, dstPort), intent)) { + ResourcePath srcPortPath = new ResourcePath(src.deviceId(), src.port()); + ResourcePath dstPortPath = new ResourcePath(dst.deviceId(), dst.port()); + List<org.onosproject.net.newresource.ResourceAllocation> allocation = + resourceService.allocate(intent.id(), srcPortPath, dstPortPath); + if (allocation.isEmpty()) { throw new IntentCompilationException("Unable to reserve ports for intent " + intent); } @@ -161,7 +165,7 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical } // Release port allocations if unsuccessful - deviceResourceService.releasePorts(intent.id()); + resourceService.release(intent.id()); throw new IntentCompilationException("Unable to find suitable lightpath for intent " + intent); } @@ -174,15 +178,12 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical * @return lambda allocated to the given path */ private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) { - for (Link link : path.links()) { - for (ResourceAllocation alloc : linkAllocs.getResourceAllocation(link)) { - if (alloc.type() == ResourceType.LAMBDA) { - return (LambdaResourceAllocation) alloc; - } - } - } - - return null; + return path.links().stream() + .flatMap(x -> linkAllocs.getResourceAllocation(x).stream()) + .filter(x -> x.type() == ResourceType.LAMBDA) + .findFirst() + .map(x -> (LambdaResourceAllocation) x) + .orElse(null); } /** @@ -215,23 +216,23 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical return false; } - LambdaResource lambda = null; + List<LambdaResource> lambdas = path.links().stream() + .flatMap(x -> allocations.getResourceAllocation(x).stream()) + .filter(x -> x.type() == ResourceType.LAMBDA) + .map(x -> ((LambdaResourceAllocation) x).lambda()) + .collect(Collectors.toList()); - for (Link link : path.links()) { - for (ResourceAllocation alloc : allocations.getResourceAllocation(link)) { - if (alloc.type() == ResourceType.LAMBDA) { - LambdaResource nextLambda = ((LambdaResourceAllocation) alloc).lambda(); - if (nextLambda == null) { - return false; - } - if (lambda == null) { - lambda = nextLambda; - continue; - } - if (!lambda.equals(nextLambda)) { - return false; - } - } + LambdaResource lambda = null; + for (LambdaResource nextLambda: lambdas) { + if (nextLambda == null) { + return false; + } + if (lambda == null) { + lambda = nextLambda; + continue; + } + if (!lambda.equals(nextLambda)) { + return false; } } diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java index ca9ae5cc..2cc45e79 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java @@ -39,7 +39,6 @@ import org.onosproject.net.intent.IntentCompiler; import org.onosproject.net.intent.IntentExtensionService; import org.onosproject.net.intent.OpticalPathIntent; import org.onosproject.net.resource.link.LinkResourceAllocations; -import org.onosproject.net.resource.link.LinkResourceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,9 +58,6 @@ public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathInte @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected CoreService coreService; - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkResourceService resourceService; - private ApplicationId appId; @Activate 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 2cd1a2e0..5226967f 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 @@ -91,6 +91,14 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ } @Override + public Optional<ResourceAllocation> getResourceAllocation(ResourcePath resource) { + checkNotNull(resource); + + Optional<ResourceConsumer> consumer = store.getConsumer(resource); + return consumer.map(x -> new ResourceAllocation(resource, x)); + } + + @Override public <T> Collection<ResourceAllocation> getResourceAllocations(ResourcePath parent, Class<T> cls) { checkNotNull(parent); checkNotNull(cls); 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 a0bc693c..8e87a07d 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 @@ -15,7 +15,8 @@ */ package org.onosproject.net.packet.impl; -import com.google.common.collect.ImmutableMap; +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; @@ -43,6 +44,7 @@ import org.onosproject.net.packet.PacketContext; import org.onosproject.net.packet.PacketEvent; import org.onosproject.net.packet.PacketPriority; import org.onosproject.net.packet.PacketProcessor; +import org.onosproject.net.packet.PacketProcessorEntry; import org.onosproject.net.packet.PacketProvider; import org.onosproject.net.packet.PacketProviderRegistry; import org.onosproject.net.packet.PacketProviderService; @@ -55,8 +57,6 @@ import org.onosproject.net.provider.AbstractProviderService; import org.slf4j.Logger; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -102,18 +102,18 @@ public class PacketManager private final DeviceListener deviceListener = new InternalDeviceListener(); - private final Map<Integer, PacketProcessor> processors = new ConcurrentHashMap<>(); + private final List<ProcessorEntry> processors = Lists.newCopyOnWriteArrayList(); private ApplicationId appId; @Activate public void activate() { eventHandlingExecutor = Executors.newSingleThreadExecutor( - groupedThreads("onos/net/packet", "event-handler")); + groupedThreads("onos/net/packet", "event-handler")); appId = coreService.getAppId(CoreService.CORE_APP_NAME); store.setDelegate(delegate); deviceService.addListener(deviceListener); - // TODO: Should we request packets for all existing devices? I believe we should. + store.existingRequests().forEach(this::pushToAllDevices); log.info("Started"); } @@ -129,19 +129,35 @@ public class PacketManager public void addProcessor(PacketProcessor processor, int priority) { checkPermission(PACKET_EVENT); checkNotNull(processor, "Processor cannot be null"); - processors.put(priority, processor); + ProcessorEntry entry = new ProcessorEntry(processor, priority); + + // Insert the new processor according to its priority. + int i = 0; + for (; i < processors.size(); i++) { + if (priority < processors.get(i).priority()) { + break; + } + } + processors.add(i, entry); } @Override public void removeProcessor(PacketProcessor processor) { checkPermission(PACKET_EVENT); checkNotNull(processor, "Processor cannot be null"); - processors.values().remove(processor); + + // Remove the processor entry. + for (int i = 0; i < processors.size(); i++) { + if (processors.get(i).processor() == processor) { + processors.remove(i); + break; + } + } } @Override - public Map<Integer, PacketProcessor> getProcessors() { - return ImmutableMap.copyOf(processors); + public List<PacketProcessorEntry> getProcessors() { + return ImmutableList.copyOf(processors); } @Override @@ -152,9 +168,7 @@ public class PacketManager checkNotNull(appId, "Application ID cannot be null"); PacketRequest request = new DefaultPacketRequest(selector, priority, appId); - if (store.requestPackets(request)) { - pushToAllDevices(request); - } + store.requestPackets(request); } @Override @@ -165,9 +179,7 @@ public class PacketManager checkNotNull(appId, "Application ID cannot be null"); PacketRequest request = new DefaultPacketRequest(selector, priority, appId); - if (store.cancelPackets(request)) { - removeFromAllDevices(request); - } + store.cancelPackets(request); } @Override @@ -176,6 +188,18 @@ public class PacketManager } /** + * Pushes all rules to the specified device. + * + * @param device device on which to install packet request flows + */ + private void pushRulesToDevice(Device device) { + log.debug("Pushing packet requests to device {}", device.id()); + for (PacketRequest request : store.existingRequests()) { + pushRule(device, request); + } + } + + /** * Pushes a packet request flow rule to all devices. * * @param request the packet request @@ -187,16 +211,13 @@ public class PacketManager } } - /** * Removes packet request flow rule from all devices. * * @param request the packet request */ private void removeFromAllDevices(PacketRequest request) { - for (Device device : deviceService.getDevices()) { - removeRule(device, request); - } + deviceService.getAvailableDevices().forEach(d -> removeRule(d, request)); } /** @@ -232,7 +253,6 @@ public class PacketManager if (!device.type().equals(Device.Type.SWITCH)) { return; } - ForwardingObjective forwarding = createBuilder(request) .remove(new ObjectiveContext() { @Override @@ -241,7 +261,6 @@ public class PacketManager request, device.id(), error); } }); - objectiveService.forward(device.id(), forwarding); } @@ -263,12 +282,10 @@ public class PacketManager } private void localEmit(OutboundPacket packet) { - final Device device = deviceService.getDevice(packet.sendThrough()); - + Device device = deviceService.getDevice(packet.sendThrough()); if (device == null) { return; } - PacketProvider packetProvider = getProvider(device.providerId()); if (packetProvider != null) { packetProvider.emit(packet); @@ -280,7 +297,9 @@ public class PacketManager return new InternalPacketProviderService(provider); } - // Personalized packet provider service issued to the supplied provider. + /** + * Personalized packet provider service issued to the supplied provider. + */ private class InternalPacketProviderService extends AbstractProviderService<PacketProvider> implements PacketProviderService { @@ -292,8 +311,10 @@ public class PacketManager @Override public void processPacket(PacketContext context) { // TODO filter packets sent to processors based on registrations - for (PacketProcessor processor : processors.values()) { - processor.process(context); + for (ProcessorEntry entry : processors) { + long start = System.nanoTime(); + entry.processor().process(context); + entry.addNanos(System.nanoTime() - start); } } @@ -307,6 +328,16 @@ public class PacketManager public void notify(PacketEvent event) { localEmit(event.subject()); } + + @Override + public void requestPackets(PacketRequest request) { + pushToAllDevices(request); + } + + @Override + public void cancelPackets(PacketRequest request) { + removeFromAllDevices(request); + } } /** @@ -319,17 +350,14 @@ public class PacketManager try { Device device = event.subject(); switch (event.type()) { - case DEVICE_ADDED: - case DEVICE_AVAILABILITY_CHANGED: - if (deviceService.isAvailable(event.subject().id())) { - log.debug("Pushing packet requests to device {}", event.subject().id()); - for (PacketRequest request : store.existingRequests()) { - pushRule(device, request); + case DEVICE_ADDED: + case DEVICE_AVAILABILITY_CHANGED: + if (deviceService.isAvailable(event.subject().id())) { + pushRulesToDevice(device); } - } - break; - default: - break; + break; + default: + break; } } catch (Exception e) { log.warn("Failed to process {}", event, e); @@ -338,4 +366,48 @@ public class PacketManager } } + /** + * Entity for tracking stats for a packet processor. + */ + private class ProcessorEntry implements PacketProcessorEntry { + private final PacketProcessor processor; + private final int priority; + private long invocations = 0; + private long nanos = 0; + + public ProcessorEntry(PacketProcessor processor, int priority) { + this.processor = processor; + this.priority = priority; + } + + @Override + public PacketProcessor processor() { + return processor; + } + + @Override + public int priority() { + return priority; + } + + @Override + public long invocations() { + return invocations; + } + + @Override + public long totalNanos() { + return nanos; + } + + @Override + public long averageNanos() { + return invocations > 0 ? nanos / invocations : 0; + } + + void addNanos(long nanos) { + this.nanos += nanos; + this.invocations++; + } + } } 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 new file mode 100644 index 00000000..6515ef31 --- /dev/null +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/statistic/impl/FlowStatisticManager.java @@ -0,0 +1,634 @@ +/*
+ * 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.statistic.impl;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+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.cli.Comparators;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTypedFlowEntry;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleEvent;
+import org.onosproject.net.flow.FlowRuleListener;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TypedStoredFlowEntry;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.statistic.DefaultLoad;
+import org.onosproject.net.statistic.FlowStatisticService;
+import org.onosproject.net.statistic.Load;
+import org.onosproject.net.statistic.FlowStatisticStore;
+import org.onosproject.net.statistic.SummaryFlowEntryWithLoad;
+import org.onosproject.net.statistic.TypedFlowEntryWithLoad;
+
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.security.AppGuard.checkPermission;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.onosproject.security.AppPermission.Type.*;
+
+/**
+ * Provides an implementation of the Flow Statistic Service.
+ */
+@Component(immediate = true, enabled = true)
+@Service
+public class FlowStatisticManager implements FlowStatisticService {
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleService flowRuleService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowStatisticStore flowStatisticStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ private final InternalFlowRuleStatsListener frListener = new InternalFlowRuleStatsListener();
+
+ @Activate
+ public void activate() {
+ flowRuleService.addListener(frListener);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ flowRuleService.removeListener(frListener);
+ log.info("Stopped");
+ }
+
+ @Override
+ public Map<ConnectPoint, SummaryFlowEntryWithLoad> loadSummary(Device device) {
+ checkPermission(STATISTIC_READ);
+
+ Map<ConnectPoint, SummaryFlowEntryWithLoad> summaryLoad = new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
+
+ if (device == null) {
+ return summaryLoad;
+ }
+
+ List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));
+
+ for (Port port : ports) {
+ ConnectPoint cp = new ConnectPoint(device.id(), port.number());
+ SummaryFlowEntryWithLoad sfe = loadSummaryPortInternal(cp);
+ summaryLoad.put(cp, sfe);
+ }
+
+ return summaryLoad;
+ }
+
+ @Override
+ public SummaryFlowEntryWithLoad loadSummary(Device device, PortNumber pNumber) {
+ checkPermission(STATISTIC_READ);
+
+ ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
+ return loadSummaryPortInternal(cp);
+ }
+
+ @Override
+ public Map<ConnectPoint, List<TypedFlowEntryWithLoad>> loadAllByType(Device device,
+ TypedStoredFlowEntry.FlowLiveType liveType,
+ Instruction.Type instType) {
+ checkPermission(STATISTIC_READ);
+
+ Map<ConnectPoint, List<TypedFlowEntryWithLoad>> allLoad = new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
+
+ if (device == null) {
+ return allLoad;
+ }
+
+ List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));
+
+ for (Port port : ports) {
+ ConnectPoint cp = new ConnectPoint(device.id(), port.number());
+ List<TypedFlowEntryWithLoad> tfel = loadAllPortInternal(cp, liveType, instType);
+ allLoad.put(cp, tfel);
+ }
+
+ return allLoad;
+ }
+
+ @Override
+ public List<TypedFlowEntryWithLoad> loadAllByType(Device device, PortNumber pNumber,
+ TypedStoredFlowEntry.FlowLiveType liveType,
+ Instruction.Type instType) {
+ checkPermission(STATISTIC_READ);
+
+ ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
+ return loadAllPortInternal(cp, liveType, instType);
+ }
+
+ @Override
+ public Map<ConnectPoint, List<TypedFlowEntryWithLoad>> loadTopnByType(Device device,
+ TypedStoredFlowEntry.FlowLiveType liveType,
+ Instruction.Type instType,
+ int topn) {
+ checkPermission(STATISTIC_READ);
+
+ Map<ConnectPoint, List<TypedFlowEntryWithLoad>> allLoad = new TreeMap<>(Comparators.CONNECT_POINT_COMPARATOR);
+
+ if (device == null) {
+ return allLoad;
+ }
+
+ List<Port> ports = new ArrayList<>(deviceService.getPorts(device.id()));
+
+ for (Port port : ports) {
+ ConnectPoint cp = new ConnectPoint(device.id(), port.number());
+ List<TypedFlowEntryWithLoad> tfel = loadTopnPortInternal(cp, liveType, instType, topn);
+ allLoad.put(cp, tfel);
+ }
+
+ return allLoad;
+ }
+
+ @Override
+ public List<TypedFlowEntryWithLoad> loadTopnByType(Device device, PortNumber pNumber,
+ TypedStoredFlowEntry.FlowLiveType liveType,
+ Instruction.Type instType,
+ int topn) {
+ checkPermission(STATISTIC_READ);
+
+ ConnectPoint cp = new ConnectPoint(device.id(), pNumber);
+ return loadTopnPortInternal(cp, liveType, instType, topn);
+ }
+
+ private SummaryFlowEntryWithLoad loadSummaryPortInternal(ConnectPoint cp) {
+ checkPermission(STATISTIC_READ);
+
+ Set<FlowEntry> currentStats;
+ Set<FlowEntry> previousStats;
+
+ TypedStatistics typedStatistics;
+ synchronized (flowStatisticStore) {
+ currentStats = flowStatisticStore.getCurrentFlowStatistic(cp);
+ if (currentStats == null) {
+ return new SummaryFlowEntryWithLoad(cp, new DefaultLoad());
+ }
+ previousStats = flowStatisticStore.getPreviousFlowStatistic(cp);
+ if (previousStats == null) {
+ return new SummaryFlowEntryWithLoad(cp, new DefaultLoad());
+ }
+ // copy to local flow entry
+ typedStatistics = new TypedStatistics(currentStats, previousStats);
+
+ // Check for validity of this stats data
+ checkLoadValidity(currentStats, previousStats);
+ }
+
+ // current and previous set is not empty!
+ Set<FlowEntry> currentSet = typedStatistics.current();
+ Set<FlowEntry> previousSet = typedStatistics.previous();
+ Load totalLoad = new DefaultLoad(aggregateBytesSet(currentSet), aggregateBytesSet(previousSet),
+ TypedFlowEntryWithLoad.avgPollInterval());
+
+ Map<FlowRule, TypedStoredFlowEntry> currentMap;
+ Map<FlowRule, TypedStoredFlowEntry> previousMap;
+
+ currentMap = typedStatistics.currentImmediate();
+ previousMap = typedStatistics.previousImmediate();
+ Load immediateLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
+ TypedFlowEntryWithLoad.shortPollInterval());
+
+ currentMap = typedStatistics.currentShort();
+ previousMap = typedStatistics.previousShort();
+ Load shortLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
+ TypedFlowEntryWithLoad.shortPollInterval());
+
+ currentMap = typedStatistics.currentMid();
+ previousMap = typedStatistics.previousMid();
+ Load midLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
+ TypedFlowEntryWithLoad.midPollInterval());
+
+ currentMap = typedStatistics.currentLong();
+ previousMap = typedStatistics.previousLong();
+ Load longLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
+ TypedFlowEntryWithLoad.longPollInterval());
+
+ currentMap = typedStatistics.currentUnknown();
+ previousMap = typedStatistics.previousUnknown();
+ Load unknownLoad = new DefaultLoad(aggregateBytesMap(currentMap), aggregateBytesMap(previousMap),
+ TypedFlowEntryWithLoad.avgPollInterval());
+
+ return new SummaryFlowEntryWithLoad(cp, totalLoad, immediateLoad, shortLoad, midLoad, longLoad, unknownLoad);
+ }
+
+ private List<TypedFlowEntryWithLoad> loadAllPortInternal(ConnectPoint cp,
+ TypedStoredFlowEntry.FlowLiveType liveType,
+ Instruction.Type instType) {
+ checkPermission(STATISTIC_READ);
+
+ List<TypedFlowEntryWithLoad> retTFEL = new ArrayList<>();
+
+ Set<FlowEntry> currentStats;
+ Set<FlowEntry> previousStats;
+
+ TypedStatistics typedStatistics;
+ synchronized (flowStatisticStore) {
+ currentStats = flowStatisticStore.getCurrentFlowStatistic(cp);
+ if (currentStats == null) {
+ return retTFEL;
+ }
+ previousStats = flowStatisticStore.getPreviousFlowStatistic(cp);
+ if (previousStats == null) {
+ return retTFEL;
+ }
+ // copy to local flow entry set
+ typedStatistics = new TypedStatistics(currentStats, previousStats);
+
+ // Check for validity of this stats data
+ checkLoadValidity(currentStats, previousStats);
+ }
+
+ // current and previous set is not empty!
+ boolean isAllLiveType = (liveType == null ? true : false); // null is all live type
+ boolean isAllInstType = (instType == null ? true : false); // null is all inst type
+
+ Map<FlowRule, TypedStoredFlowEntry> currentMap;
+ Map<FlowRule, TypedStoredFlowEntry> previousMap;
+
+ if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.IMMEDIATE_FLOW) {
+ currentMap = typedStatistics.currentImmediate();
+ previousMap = typedStatistics.previousImmediate();
+
+ List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
+ isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
+ if (fel.size() > 0) {
+ retTFEL.addAll(fel);
+ }
+ }
+
+ if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.SHORT_FLOW) {
+ currentMap = typedStatistics.currentShort();
+ previousMap = typedStatistics.previousShort();
+
+ List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
+ isAllInstType, instType, TypedFlowEntryWithLoad.shortPollInterval());
+ if (fel.size() > 0) {
+ retTFEL.addAll(fel);
+ }
+ }
+
+ if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.MID_FLOW) {
+ currentMap = typedStatistics.currentMid();
+ previousMap = typedStatistics.previousMid();
+
+ List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
+ isAllInstType, instType, TypedFlowEntryWithLoad.midPollInterval());
+ if (fel.size() > 0) {
+ retTFEL.addAll(fel);
+ }
+ }
+
+ if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.LONG_FLOW) {
+ currentMap = typedStatistics.currentLong();
+ previousMap = typedStatistics.previousLong();
+
+ List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
+ isAllInstType, instType, TypedFlowEntryWithLoad.longPollInterval());
+ if (fel.size() > 0) {
+ retTFEL.addAll(fel);
+ }
+ }
+
+ if (isAllLiveType || liveType == TypedStoredFlowEntry.FlowLiveType.UNKNOWN_FLOW) {
+ currentMap = typedStatistics.currentUnknown();
+ previousMap = typedStatistics.previousUnknown();
+
+ List<TypedFlowEntryWithLoad> fel = typedFlowEntryLoadByInstInternal(cp, currentMap, previousMap,
+ isAllInstType, instType, TypedFlowEntryWithLoad.avgPollInterval());
+ if (fel.size() > 0) {
+ retTFEL.addAll(fel);
+ }
+ }
+
+ return retTFEL;
+ }
+
+ private List<TypedFlowEntryWithLoad> typedFlowEntryLoadByInstInternal(ConnectPoint cp,
+ Map<FlowRule, TypedStoredFlowEntry> currentMap,
+ Map<FlowRule, TypedStoredFlowEntry> previousMap,
+ boolean isAllInstType,
+ Instruction.Type instType,
+ int liveTypePollInterval) {
+ List<TypedFlowEntryWithLoad> fel = new ArrayList<>();
+
+ for (TypedStoredFlowEntry tfe : currentMap.values()) {
+ if (isAllInstType ||
+ tfe.treatment().allInstructions().stream().
+ filter(i -> i.type() == instType).
+ findAny().isPresent()) {
+ long currentBytes = tfe.bytes();
+ long previousBytes = previousMap.getOrDefault(tfe, new DefaultTypedFlowEntry((FlowRule) tfe)).bytes();
+ Load fLoad = new DefaultLoad(currentBytes, previousBytes, liveTypePollInterval);
+ fel.add(new TypedFlowEntryWithLoad(cp, tfe, fLoad));
+ }
+ }
+
+ return fel;
+ }
+
+ private List<TypedFlowEntryWithLoad> loadTopnPortInternal(ConnectPoint cp,
+ TypedStoredFlowEntry.FlowLiveType liveType,
+ Instruction.Type instType,
+ int topn) {
+ List<TypedFlowEntryWithLoad> fel = loadAllPortInternal(cp, liveType, instType);
+
+ // Sort with descending order of load
+ List<TypedFlowEntryWithLoad> tfel =
+ fel.stream().sorted(Comparators.TYPEFLOWENTRY_WITHLOAD_COMPARATOR).
+ limit(topn).collect(Collectors.toList());
+
+ return tfel;
+ }
+
+ private long aggregateBytesSet(Set<FlowEntry> setFE) {
+ return setFE.stream().mapToLong(FlowEntry::bytes).sum();
+ }
+
+ private long aggregateBytesMap(Map<FlowRule, TypedStoredFlowEntry> mapFE) {
+ return mapFE.values().stream().mapToLong(FlowEntry::bytes).sum();
+ }
+
+ /**
+ * Internal data class holding two set of typed flow entries.
+ */
+ private static class TypedStatistics {
+ private final ImmutableSet<FlowEntry> currentAll;
+ private final ImmutableSet<FlowEntry> previousAll;
+
+ private final Map<FlowRule, TypedStoredFlowEntry> currentImmediate = new HashMap<>();
+ private final Map<FlowRule, TypedStoredFlowEntry> previousImmediate = new HashMap<>();
+
+ private final Map<FlowRule, TypedStoredFlowEntry> currentShort = new HashMap<>();
+ private final Map<FlowRule, TypedStoredFlowEntry> previousShort = new HashMap<>();
+
+ private final Map<FlowRule, TypedStoredFlowEntry> currentMid = new HashMap<>();
+ private final Map<FlowRule, TypedStoredFlowEntry> previousMid = new HashMap<>();
+
+ private final Map<FlowRule, TypedStoredFlowEntry> currentLong = new HashMap<>();
+ private final Map<FlowRule, TypedStoredFlowEntry> previousLong = new HashMap<>();
+
+ private final Map<FlowRule, TypedStoredFlowEntry> currentUnknown = new HashMap<>();
+ private final Map<FlowRule, TypedStoredFlowEntry> previousUnknown = new HashMap<>();
+
+ public TypedStatistics(Set<FlowEntry> current, Set<FlowEntry> previous) {
+ this.currentAll = ImmutableSet.copyOf(checkNotNull(current));
+ this.previousAll = ImmutableSet.copyOf(checkNotNull(previous));
+
+ currentAll.forEach(fe -> {
+ TypedStoredFlowEntry tfe = TypedFlowEntryWithLoad.newTypedStoredFlowEntry(fe);
+
+ switch (tfe.flowLiveType()) {
+ case IMMEDIATE_FLOW:
+ currentImmediate.put(fe, tfe);
+ break;
+ case SHORT_FLOW:
+ currentShort.put(fe, tfe);
+ break;
+ case MID_FLOW:
+ currentMid.put(fe, tfe);
+ break;
+ case LONG_FLOW:
+ currentLong.put(fe, tfe);
+ break;
+ default:
+ currentUnknown.put(fe, tfe);
+ break;
+ }
+ });
+
+ previousAll.forEach(fe -> {
+ TypedStoredFlowEntry tfe = TypedFlowEntryWithLoad.newTypedStoredFlowEntry(fe);
+
+ switch (tfe.flowLiveType()) {
+ case IMMEDIATE_FLOW:
+ if (currentImmediate.containsKey(fe)) {
+ previousImmediate.put(fe, tfe);
+ } else if (currentShort.containsKey(fe)) {
+ previousShort.put(fe, tfe);
+ } else if (currentMid.containsKey(fe)) {
+ previousMid.put(fe, tfe);
+ } else if (currentLong.containsKey(fe)) {
+ previousLong.put(fe, tfe);
+ } else {
+ previousUnknown.put(fe, tfe);
+ }
+ break;
+ case SHORT_FLOW:
+ if (currentShort.containsKey(fe)) {
+ previousShort.put(fe, tfe);
+ } else if (currentMid.containsKey(fe)) {
+ previousMid.put(fe, tfe);
+ } else if (currentLong.containsKey(fe)) {
+ previousLong.put(fe, tfe);
+ } else {
+ previousUnknown.put(fe, tfe);
+ }
+ break;
+ case MID_FLOW:
+ if (currentMid.containsKey(fe)) {
+ previousMid.put(fe, tfe);
+ } else if (currentLong.containsKey(fe)) {
+ previousLong.put(fe, tfe);
+ } else {
+ previousUnknown.put(fe, tfe);
+ }
+ break;
+ case LONG_FLOW:
+ if (currentLong.containsKey(fe)) {
+ previousLong.put(fe, tfe);
+ } else {
+ previousUnknown.put(fe, tfe);
+ }
+ break;
+ default:
+ previousUnknown.put(fe, tfe);
+ break;
+ }
+ });
+ }
+
+ /**
+ * Returns flow entries as the current value.
+ *
+ * @return flow entries as the current value
+ */
+ public ImmutableSet<FlowEntry> current() {
+ return currentAll;
+ }
+
+ /**
+ * Returns flow entries as the previous value.
+ *
+ * @return flow entries as the previous value
+ */
+ public ImmutableSet<FlowEntry> previous() {
+ return previousAll;
+ }
+
+ public Map<FlowRule, TypedStoredFlowEntry> currentImmediate() {
+ return currentImmediate;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> previousImmediate() {
+ return previousImmediate;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> currentShort() {
+ return currentShort;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> previousShort() {
+ return previousShort;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> currentMid() {
+ return currentMid;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> previousMid() {
+ return previousMid;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> currentLong() {
+ return currentLong;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> previousLong() {
+ return previousLong;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> currentUnknown() {
+ return currentUnknown;
+ }
+ public Map<FlowRule, TypedStoredFlowEntry> previousUnknown() {
+ return previousUnknown;
+ }
+
+ /**
+ * Validates values are not empty.
+ *
+ * @return false if either of the sets is empty. Otherwise, true.
+ */
+ public boolean isValid() {
+ return !(currentAll.isEmpty() || previousAll.isEmpty());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(currentAll, previousAll);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof TypedStatistics)) {
+ return false;
+ }
+ final TypedStatistics other = (TypedStatistics) obj;
+ return Objects.equals(this.currentAll, other.currentAll) &&
+ Objects.equals(this.previousAll, other.previousAll);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("current", currentAll)
+ .add("previous", previousAll)
+ .toString();
+ }
+ }
+
+ private void checkLoadValidity(Set<FlowEntry> current, Set<FlowEntry> previous) {
+ current.stream().forEach(c -> {
+ FlowEntry f = previous.stream().filter(p -> c.equals(p)).
+ findAny().orElse(null);
+ if (f != null && c.bytes() < f.bytes()) {
+ log.debug("FlowStatisticManager:checkLoadValidity():" +
+ "Error: " + c + " :Previous bytes=" + f.bytes() +
+ " is larger than current bytes=" + c.bytes() + " !!!");
+ }
+ });
+
+ }
+
+ /**
+ * Creates a predicate that checks the instruction type of a flow entry is the same as
+ * the specified instruction type.
+ *
+ * @param instType instruction type to be checked
+ * @return predicate
+ */
+ private static Predicate<FlowEntry> hasInstructionType(Instruction.Type instType) {
+ return new Predicate<FlowEntry>() {
+ @Override
+ public boolean apply(FlowEntry flowEntry) {
+ List<Instruction> allInstructions = flowEntry.treatment().allInstructions();
+
+ return allInstructions.stream().filter(i -> i.type() == instType).findAny().isPresent();
+ }
+ };
+ }
+
+ /**
+ * Internal flow rule event listener for FlowStatisticManager.
+ */
+ private class InternalFlowRuleStatsListener implements FlowRuleListener {
+
+ @Override
+ public void event(FlowRuleEvent event) {
+ FlowRule rule = event.subject();
+ switch (event.type()) {
+ case RULE_ADDED:
+ if (rule instanceof FlowEntry) {
+ flowStatisticStore.addFlowStatistic((FlowEntry) rule);
+ }
+ break;
+ case RULE_UPDATED:
+ flowStatisticStore.updateFlowStatistic((FlowEntry) rule);
+ break;
+ case RULE_ADD_REQUESTED:
+ break;
+ case RULE_REMOVE_REQUESTED:
+ break;
+ case RULE_REMOVED:
+ flowStatisticStore.removeFlowStatistic(rule);
+ break;
+ default:
+ log.warn("Unknown flow rule event {}", event);
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java index a238c7fb..8347ee38 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/PathManager.java @@ -27,6 +27,8 @@ import org.apache.felix.scr.annotations.Service; import org.onosproject.net.ConnectPoint; import org.onosproject.net.DefaultEdgeLink; import org.onosproject.net.DefaultPath; +import org.onosproject.net.DisjointPath; +import org.onosproject.net.DefaultDisjointPath; import org.onosproject.net.DeviceId; import org.onosproject.net.EdgeLink; import org.onosproject.net.ElementId; @@ -46,6 +48,8 @@ import org.slf4j.Logger; import java.util.List; import java.util.Set; +import java.util.Map; + import static com.google.common.base.Preconditions.checkNotNull; import static org.slf4j.LoggerFactory.getLogger; @@ -128,6 +132,84 @@ public class PathManager implements PathService { return edgeToEdgePaths(srcEdge, dstEdge, paths); } + @Override + public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) { + return getDisjointPaths(src, dst, (LinkWeight) null); + } + + @Override + public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) { + checkNotNull(src, ELEMENT_ID_NULL); + checkNotNull(dst, ELEMENT_ID_NULL); + + // Get the source and destination edge locations + EdgeLink srcEdge = getEdgeLink(src, true); + EdgeLink dstEdge = getEdgeLink(dst, false); + + // If either edge is null, bail with no paths. + if (srcEdge == null || dstEdge == null) { + return ImmutableSet.of(); + } + + DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src; + DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst; + + // If the source and destination are on the same edge device, there + // is just one path, so build it and return it. + if (srcDevice.equals(dstDevice)) { + return edgeToEdgePathsDisjoint(srcEdge, dstEdge); + } + + // Otherwise get all paths between the source and destination edge + // devices. + Topology topology = topologyService.currentTopology(); + Set<DisjointPath> paths = weight == null ? + topologyService.getDisjointPaths(topology, srcDevice, dstDevice) : + topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight); + + return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths); + } + + @Override + public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, + Map<Link, Object> riskProfile) { + return getDisjointPaths(src, dst, null, riskProfile); + } + + @Override + public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight, + Map<Link, Object> riskProfile) { + checkNotNull(src, ELEMENT_ID_NULL); + checkNotNull(dst, ELEMENT_ID_NULL); + + // Get the source and destination edge locations + EdgeLink srcEdge = getEdgeLink(src, true); + EdgeLink dstEdge = getEdgeLink(dst, false); + + // If either edge is null, bail with no paths. + if (srcEdge == null || dstEdge == null) { + return ImmutableSet.of(); + } + + DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src; + DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst; + + // If the source and destination are on the same edge device, there + // is just one path, so build it and return it. + if (srcDevice.equals(dstDevice)) { + return edgeToEdgePathsDisjoint(srcEdge, dstEdge); + } + + // Otherwise get all paths between the source and destination edge + // devices. + Topology topology = topologyService.currentTopology(); + Set<DisjointPath> paths = weight == null ? + topologyService.getDisjointPaths(topology, srcDevice, dstDevice, riskProfile) : + topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight, riskProfile); + + return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths); + } + // Finds the host edge link if the element ID is a host id of an existing // host. Otherwise, if the host does not exist, it returns null and if // the element ID is not a host ID, returns NOT_HOST edge link. @@ -162,6 +244,20 @@ public class PathManager implements PathService { return endToEndPaths; } + private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink) { + Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(1); + endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, null)); + return endToEndPaths; + } + + private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink, Set<DisjointPath> paths) { + Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size()); + for (DisjointPath path : paths) { + endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, path)); + } + return endToEndPaths; + } + // Produces a direct edge-to-edge path. private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) { List<Link> links = Lists.newArrayListWithCapacity(2); @@ -179,6 +275,13 @@ public class PathManager implements PathService { return new DefaultPath(PID, links, 2); } + // Produces a direct edge-to-edge path. + private DisjointPath edgeToEdgePathD(EdgeLink srcLink, EdgeLink dstLink, DisjointPath path) { + return new DefaultDisjointPath(PID, (DefaultPath) edgeToEdgePath(srcLink, dstLink, path.primary()), + (DefaultPath) edgeToEdgePath(srcLink, dstLink, path.backup())); + } + + // Special value for edge link to represent that this is really not an // edge link since the src or dst are really an infrastructure device. private static class NotHost extends DefaultEdgeLink implements EdgeLink { diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java index 04c4f1c1..4425e1c1 100644 --- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java +++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/topology/impl/TopologyManager.java @@ -21,6 +21,7 @@ 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.net.DisjointPath; import org.onosproject.net.provider.AbstractListenerProviderRegistry; import org.onosproject.event.Event; import org.onosproject.net.ConnectPoint; @@ -46,6 +47,7 @@ import org.slf4j.Logger; import java.util.List; import java.util.Set; +import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; import static org.onosproject.security.AppGuard.checkPermission; @@ -60,7 +62,7 @@ import static org.onosproject.security.AppPermission.Type.*; @Service public class TopologyManager extends AbstractListenerProviderRegistry<TopologyEvent, TopologyListener, - TopologyProvider, TopologyProviderService> + TopologyProvider, TopologyProviderService> implements TopologyService, TopologyProviderRegistry { public static final String TOPOLOGY_NULL = "Topology cannot be null"; @@ -68,6 +70,7 @@ public class TopologyManager private static final String CLUSTER_ID_NULL = "Cluster ID cannot be null"; private static final String CLUSTER_NULL = "Topology cluster cannot be null"; public static final String CONNECTION_POINT_NULL = "Connection point cannot be null"; + public static final String LINK_WEIGHT_NULL = "Link weight cannot be null"; private final Logger log = getLogger(getClass()); @@ -162,6 +165,44 @@ public class TopologyManager } @Override + public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst) { + checkNotNull(topology, TOPOLOGY_NULL); + checkNotNull(src, DEVICE_ID_NULL); + checkNotNull(dst, DEVICE_ID_NULL); + return store.getDisjointPaths(topology, src, dst); + } + + @Override + public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, + DeviceId dst, LinkWeight weight) { + checkNotNull(topology, TOPOLOGY_NULL); + checkNotNull(src, DEVICE_ID_NULL); + checkNotNull(dst, DEVICE_ID_NULL); + checkNotNull(weight, LINK_WEIGHT_NULL); + return store.getDisjointPaths(topology, src, dst, weight); + } + + @Override + public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst, + Map<Link, Object> riskProfile) { + checkNotNull(topology, TOPOLOGY_NULL); + checkNotNull(src, DEVICE_ID_NULL); + checkNotNull(dst, DEVICE_ID_NULL); + return store.getDisjointPaths(topology, src, dst, riskProfile); + } + + @Override + public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, + DeviceId dst, LinkWeight weight, + Map<Link, Object> riskProfile) { + checkNotNull(topology, TOPOLOGY_NULL); + checkNotNull(src, DEVICE_ID_NULL); + checkNotNull(dst, DEVICE_ID_NULL); + checkNotNull(weight, LINK_WEIGHT_NULL); + return store.getDisjointPaths(topology, src, dst, weight, riskProfile); + } + + @Override public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { checkPermission(TOPOLOGY_READ); checkNotNull(topology, TOPOLOGY_NULL); diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/cfg/impl/ComponentConfigLoaderTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/cfg/impl/ComponentConfigLoaderTest.java new file mode 100644 index 00000000..0320cf77 --- /dev/null +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/cfg/impl/ComponentConfigLoaderTest.java @@ -0,0 +1,126 @@ +/* + * 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.cfg.impl; + +import com.google.common.collect.ImmutableSet; +import com.google.common.io.Files; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfg.ComponentConfigAdapter; +import org.slf4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.util.Set; + +import static com.google.common.io.ByteStreams.toByteArray; +import static com.google.common.io.Files.write; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * UnitTest for ComponentLoader. + */ +public class ComponentConfigLoaderTest { + + static final File TEST_DIR = Files.createTempDir(); + + private static final String FOO_COMPONENT = "fooComponent"; + + private ComponentConfigLoader loader; + + private TestConfigService service; + + private final Logger log = getLogger(getClass()); + + /* + * Method to SetUp the test environment with test file, a config loader a service, + * and assign it to the loader.configService for the test. + */ + @Before + public void setUp() { + ComponentConfigLoader.cfgFile = new File(TEST_DIR, "test.json"); + loader = new ComponentConfigLoader(); + service = new TestConfigService(); + loader.configService = service; + } + + /* + * Tests that the component in the json receives the correct configuration. + */ + @Test + public void basics() throws IOException { + stageTestResource("basic.json"); + loader.activate(); + assertEquals("incorrect component", FOO_COMPONENT, service.component); + } + + /* + * Tests that the component is null if the file has a bad configuration format + * for which it yielded an exception. Can't test the exception because it happens + * in a different thread. + */ + @Test + public void badConfig() throws IOException { + stageTestResource("badConfig.json"); + loader.activate(); + assertNull("incorrect configuration", service.component); + + } + + /* + * Writes the necessary file for the tests in the temporary directory + */ + static void stageTestResource(String name) throws IOException { + byte[] bytes = toByteArray(ComponentConfigLoaderTest.class.getResourceAsStream(name)); + write(bytes, ComponentConfigLoader.cfgFile); + } + + /* + * Mockup class for the config service. + */ + private class TestConfigService extends ComponentConfigAdapter { + + protected String component; + protected String name; + protected String value; + + @Override + public Set<String> getComponentNames() { + return ImmutableSet.of(FOO_COMPONENT); + } + + @Override + public void preSetProperty(String componentName, String name, String value) { + log.info("preSet"); + this.component = componentName; + this.name = name; + this.value = value; + + } + + @Override + public void setProperty(String componentName, String name, String value) { + log.info("Set"); + this.component = componentName; + this.name = name; + this.value = value; + + } + } +}
\ No newline at end of file diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java index d167197a..3cd2ca2b 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java @@ -23,10 +23,12 @@ import org.junit.Before; import org.junit.Test; import org.onlab.packet.ARP; import org.onlab.packet.Ethernet; +import org.onlab.packet.IPv6; import org.onlab.packet.IpAddress; import org.onlab.packet.IpPrefix; import org.onlab.packet.MacAddress; import org.onlab.packet.VlanId; +import org.onlab.packet.ndp.NeighborSolicitation; import org.onosproject.incubator.net.intf.Interface; import org.onosproject.incubator.net.intf.InterfaceService; import org.onosproject.net.ConnectPoint; @@ -64,14 +66,22 @@ import static org.junit.Assert.assertTrue; public class HostMonitorTest { - private static final IpAddress TARGET_IP_ADDR = + private static final IpAddress TARGET_IPV4_ADDR = IpAddress.valueOf("10.0.0.1"); - private static final IpAddress SOURCE_ADDR = + private static final IpAddress SOURCE_IPV4_ADDR = IpAddress.valueOf("10.0.0.99"); private static final InterfaceIpAddress IA1 = - new InterfaceIpAddress(SOURCE_ADDR, IpPrefix.valueOf("10.0.0.0/24")); + new InterfaceIpAddress(SOURCE_IPV4_ADDR, IpPrefix.valueOf("10.0.0.0/24")); private MacAddress sourceMac = MacAddress.valueOf(1L); + private static final IpAddress TARGET_IPV6_ADDR = + IpAddress.valueOf("1000::1"); + private static final IpAddress SOURCE_IPV6_ADDR = + IpAddress.valueOf("1000::f"); + private static final InterfaceIpAddress IA2 = + new InterfaceIpAddress(SOURCE_IPV6_ADDR, IpPrefix.valueOf("1000::/64")); + private MacAddress sourceMac2 = MacAddress.valueOf(2L); + private EdgePortService edgePortService; private HostMonitor hostMonitor; @@ -90,7 +100,36 @@ public class HostMonitorTest { } @Test - public void testMonitorHostExists() throws Exception { + public void testMonitorIpv4HostExists() throws Exception { + ProviderId id = new ProviderId("fake://", "id"); + + Host host = createMock(Host.class); + expect(host.providerId()).andReturn(id); + replay(host); + + HostManager hostManager = createMock(HostManager.class); + expect(hostManager.getHostsByIp(TARGET_IPV4_ADDR)) + .andReturn(Collections.singleton(host)); + replay(hostManager); + + HostProvider hostProvider = createMock(HostProvider.class); + expect(hostProvider.id()).andReturn(id).anyTimes(); + hostProvider.triggerProbe(host); + expectLastCall().once(); + replay(hostProvider); + + hostMonitor = new HostMonitor(null, hostManager, null, edgePortService); + + hostMonitor.registerHostProvider(hostProvider); + hostMonitor.addMonitoringFor(TARGET_IPV4_ADDR); + + hostMonitor.run(null); + + verify(hostProvider); + } + + @Test + public void testMonitorIpv6HostExists() throws Exception { ProviderId id = new ProviderId("fake://", "id"); Host host = createMock(Host.class); @@ -98,7 +137,7 @@ public class HostMonitorTest { replay(host); HostManager hostManager = createMock(HostManager.class); - expect(hostManager.getHostsByIp(TARGET_IP_ADDR)) + expect(hostManager.getHostsByIp(TARGET_IPV6_ADDR)) .andReturn(Collections.singleton(host)); replay(hostManager); @@ -111,7 +150,7 @@ public class HostMonitorTest { hostMonitor = new HostMonitor(null, hostManager, null, edgePortService); hostMonitor.registerHostProvider(hostProvider); - hostMonitor.addMonitoringFor(TARGET_IP_ADDR); + hostMonitor.addMonitoringFor(TARGET_IPV6_ADDR); hostMonitor.run(null); @@ -119,7 +158,7 @@ public class HostMonitorTest { } @Test - public void testMonitorHostDoesNotExist() throws Exception { + public void testMonitorIpv4HostDoesNotExist() throws Exception { HostManager hostManager = createMock(HostManager.class); @@ -140,12 +179,12 @@ public class HostMonitorTest { ConnectPoint cp = new ConnectPoint(devId, portNum); - expect(hostManager.getHostsByIp(TARGET_IP_ADDR)) + expect(hostManager.getHostsByIp(TARGET_IPV4_ADDR)) .andReturn(Collections.emptySet()).anyTimes(); replay(hostManager); InterfaceService interfaceService = createMock(InterfaceService.class); - expect(interfaceService.getMatchingInterface(TARGET_IP_ADDR)) + expect(interfaceService.getMatchingInterface(TARGET_IPV4_ADDR)) .andReturn(new Interface(cp, Collections.singleton(IA1), sourceMac, VlanId.NONE)) .anyTimes(); replay(interfaceService); @@ -156,7 +195,7 @@ public class HostMonitorTest { // Run the test hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService); - hostMonitor.addMonitoringFor(TARGET_IP_ADDR); + hostMonitor.addMonitoringFor(TARGET_IPV4_ADDR); hostMonitor.run(null); @@ -178,16 +217,85 @@ public class HostMonitorTest { Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length); assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID()); ARP arp = (ARP) eth.getPayload(); - assertArrayEquals(SOURCE_ADDR.toOctets(), + assertArrayEquals(SOURCE_IPV4_ADDR.toOctets(), arp.getSenderProtocolAddress()); assertArrayEquals(sourceMac.toBytes(), arp.getSenderHardwareAddress()); - assertArrayEquals(TARGET_IP_ADDR.toOctets(), + assertArrayEquals(TARGET_IPV4_ADDR.toOctets(), arp.getTargetProtocolAddress()); } @Test - public void testMonitorHostDoesNotExistWithVlan() throws Exception { + public void testMonitorIpv6HostDoesNotExist() throws Exception { + + HostManager hostManager = createMock(HostManager.class); + + DeviceId devId = DeviceId.deviceId("fake"); + + Device device = createMock(Device.class); + expect(device.id()).andReturn(devId).anyTimes(); + replay(device); + + PortNumber portNum = PortNumber.portNumber(2L); + + Port port = createMock(Port.class); + expect(port.number()).andReturn(portNum).anyTimes(); + replay(port); + + TestDeviceService deviceService = new TestDeviceService(); + deviceService.addDevice(device, Collections.singleton(port)); + + ConnectPoint cp = new ConnectPoint(devId, portNum); + + expect(hostManager.getHostsByIp(TARGET_IPV6_ADDR)) + .andReturn(Collections.emptySet()).anyTimes(); + replay(hostManager); + + InterfaceService interfaceService = createMock(InterfaceService.class); + expect(interfaceService.getMatchingInterface(TARGET_IPV6_ADDR)) + .andReturn(new Interface(cp, Collections.singleton(IA2), sourceMac2, VlanId.NONE)) + .anyTimes(); + replay(interfaceService); + + TestPacketService packetService = new TestPacketService(); + + + // Run the test + hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService); + + hostMonitor.addMonitoringFor(TARGET_IPV6_ADDR); + hostMonitor.run(null); + + + // Check that a packet was sent to our PacketService and that it has + // the properties we expect + assertEquals(1, packetService.packets.size()); + OutboundPacket packet = packetService.packets.get(0); + + // Check the output port is correct + assertEquals(1, packet.treatment().immediate().size()); + Instruction instruction = packet.treatment().immediate().get(0); + assertTrue(instruction instanceof OutputInstruction); + OutputInstruction oi = (OutputInstruction) instruction; + assertEquals(portNum, oi.port()); + + // Check the output packet is correct (well the important bits anyway) + final byte[] pktData = new byte[packet.data().remaining()]; + packet.data().get(pktData); + Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length); + assertEquals(Ethernet.VLAN_UNTAGGED, eth.getVlanID()); + IPv6 ipv6 = (IPv6) eth.getPayload(); + assertArrayEquals(SOURCE_IPV6_ADDR.toOctets(), ipv6.getSourceAddress()); + + NeighborSolicitation ns = + (NeighborSolicitation) ipv6.getPayload().getPayload(); + assertArrayEquals(sourceMac2.toBytes(), ns.getOptions().get(0).data()); + + assertArrayEquals(TARGET_IPV6_ADDR.toOctets(), ns.getTargetAddress()); + } + + @Test + public void testMonitorIpv4HostDoesNotExistWithVlan() throws Exception { HostManager hostManager = createMock(HostManager.class); @@ -209,12 +317,12 @@ public class HostMonitorTest { ConnectPoint cp = new ConnectPoint(devId, portNum); - expect(hostManager.getHostsByIp(TARGET_IP_ADDR)) + expect(hostManager.getHostsByIp(TARGET_IPV4_ADDR)) .andReturn(Collections.emptySet()).anyTimes(); replay(hostManager); InterfaceService interfaceService = createMock(InterfaceService.class); - expect(interfaceService.getMatchingInterface(TARGET_IP_ADDR)) + expect(interfaceService.getMatchingInterface(TARGET_IPV4_ADDR)) .andReturn(new Interface(cp, Collections.singleton(IA1), sourceMac, VlanId.vlanId(vlan))) .anyTimes(); replay(interfaceService); @@ -225,7 +333,7 @@ public class HostMonitorTest { // Run the test hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService); - hostMonitor.addMonitoringFor(TARGET_IP_ADDR); + hostMonitor.addMonitoringFor(TARGET_IPV4_ADDR); hostMonitor.run(null); @@ -247,14 +355,84 @@ public class HostMonitorTest { Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length); assertEquals(vlan, eth.getVlanID()); ARP arp = (ARP) eth.getPayload(); - assertArrayEquals(SOURCE_ADDR.toOctets(), + assertArrayEquals(SOURCE_IPV4_ADDR.toOctets(), arp.getSenderProtocolAddress()); assertArrayEquals(sourceMac.toBytes(), arp.getSenderHardwareAddress()); - assertArrayEquals(TARGET_IP_ADDR.toOctets(), + assertArrayEquals(TARGET_IPV4_ADDR.toOctets(), arp.getTargetProtocolAddress()); } + @Test + public void testMonitorIpv6HostDoesNotExistWithVlan() throws Exception { + + HostManager hostManager = createMock(HostManager.class); + + DeviceId devId = DeviceId.deviceId("fake"); + short vlan = 5; + + Device device = createMock(Device.class); + expect(device.id()).andReturn(devId).anyTimes(); + replay(device); + + PortNumber portNum = PortNumber.portNumber(1L); + + Port port = createMock(Port.class); + expect(port.number()).andReturn(portNum).anyTimes(); + replay(port); + + TestDeviceService deviceService = new TestDeviceService(); + deviceService.addDevice(device, Collections.singleton(port)); + + ConnectPoint cp = new ConnectPoint(devId, portNum); + + expect(hostManager.getHostsByIp(TARGET_IPV6_ADDR)) + .andReturn(Collections.emptySet()).anyTimes(); + replay(hostManager); + + InterfaceService interfaceService = createMock(InterfaceService.class); + expect(interfaceService.getMatchingInterface(TARGET_IPV6_ADDR)) + .andReturn(new Interface(cp, Collections.singleton(IA2), sourceMac2, VlanId.vlanId(vlan))) + .anyTimes(); + replay(interfaceService); + + TestPacketService packetService = new TestPacketService(); + + + // Run the test + hostMonitor = new HostMonitor(packetService, hostManager, interfaceService, edgePortService); + + hostMonitor.addMonitoringFor(TARGET_IPV6_ADDR); + hostMonitor.run(null); + + + // Check that a packet was sent to our PacketService and that it has + // the properties we expect + assertEquals(1, packetService.packets.size()); + OutboundPacket packet = packetService.packets.get(0); + + // Check the output port is correct + assertEquals(1, packet.treatment().immediate().size()); + Instruction instruction = packet.treatment().immediate().get(0); + assertTrue(instruction instanceof OutputInstruction); + OutputInstruction oi = (OutputInstruction) instruction; + assertEquals(portNum, oi.port()); + + // Check the output packet is correct (well the important bits anyway) + final byte[] pktData = new byte[packet.data().remaining()]; + packet.data().get(pktData); + Ethernet eth = Ethernet.deserializer().deserialize(pktData, 0, pktData.length); + assertEquals(vlan, eth.getVlanID()); + IPv6 ipv6 = (IPv6) eth.getPayload(); + assertArrayEquals(SOURCE_IPV6_ADDR.toOctets(), ipv6.getSourceAddress()); + + NeighborSolicitation ns = + (NeighborSolicitation) ipv6.getPayload().getPayload(); + assertArrayEquals(sourceMac2.toBytes(), ns.getOptions().get(0).data()); + + assertArrayEquals(TARGET_IPV6_ADDR.toOctets(), ns.getTargetAddress()); + } + class TestPacketService extends PacketServiceAdapter { List<OutboundPacket> packets = new ArrayList<>(); diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java index 4bf32f43..3f40de09 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java @@ -157,7 +157,7 @@ public class IntentManagerTest { private static class MockInstallableIntent extends FlowRuleIntent { public MockInstallableIntent() { - super(APPID, Collections.singletonList(new MockFlowRule(100))); + super(APPID, Collections.singletonList(new MockFlowRule(100)), Collections.emptyList()); } } diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java index eb7a3936..03d664d3 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java @@ -31,8 +31,7 @@ import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.IntentTestsMocks; import org.onosproject.net.intent.LinkCollectionIntent; import org.onosproject.net.intent.MultiPointToSinglePointIntent; -import org.onosproject.net.topology.LinkWeight; -import org.onosproject.net.topology.PathService; +import org.onosproject.net.topology.PathServiceAdapter; import java.util.HashSet; import java.util.List; @@ -60,7 +59,7 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes /** * Mock path service for creating paths within the test. */ - private static class MockPathService implements PathService { + private static class MockPathService extends PathServiceAdapter { final String[] pathHops; @@ -86,11 +85,6 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes return result; } - - @Override - public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) { - return null; - } } /** diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java index 2f40b37a..38a116dd 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java @@ -27,18 +27,12 @@ import org.onosproject.net.DefaultLink; import org.onosproject.net.DefaultPath; import org.onosproject.net.Link; import org.onosproject.net.OchSignalType; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.intent.FlowRuleIntent; import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.IntentExtensionService; -import org.onosproject.net.intent.IntentTestsMocks; import org.onosproject.net.intent.MockIdGenerator; import org.onosproject.net.intent.OpticalPathIntent; -import org.onosproject.net.provider.ProviderId; import java.util.Arrays; import java.util.Collection; @@ -63,16 +57,11 @@ public class OpticalPathIntentCompilerTest { private final IdGenerator idGenerator = new MockIdGenerator(); private OpticalPathIntentCompiler sut; - private final TrafficSelector selector = DefaultTrafficSelector.builder().build(); - private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); private final ApplicationId appId = new TestApplicationId("test"); - private final ProviderId pid = new ProviderId("of", "test"); private final ConnectPoint d1p1 = connectPoint("s1", 0); private final ConnectPoint d2p0 = connectPoint("s2", 0); private final ConnectPoint d2p1 = connectPoint("s2", 1); private final ConnectPoint d3p1 = connectPoint("s3", 1); - private final ConnectPoint d3p0 = connectPoint("s3", 10); - private final ConnectPoint d1p0 = connectPoint("s1", 10); private final List<Link> links = Arrays.asList( new DefaultLink(PID, d1p1, d2p0, DIRECT), @@ -103,7 +92,6 @@ public class OpticalPathIntentCompilerTest { intentExtensionService.registerCompiler(OpticalPathIntent.class, sut); intentExtensionService.unregisterCompiler(OpticalPathIntent.class); sut.intentManager = intentExtensionService; - sut.resourceService = new IntentTestsMocks.MockResourceService(); replay(coreService, intentExtensionService); } diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java index 2a2d0b54..1911da56 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/PathManagerTest.java @@ -23,13 +23,11 @@ import org.onosproject.net.ElementId; import org.onosproject.net.Host; import org.onosproject.net.HostId; import org.onosproject.net.Path; -import org.onosproject.net.host.HostService; import org.onosproject.net.host.HostServiceAdapter; import org.onosproject.net.provider.ProviderId; import org.onosproject.net.topology.LinkWeight; import org.onosproject.net.topology.PathService; import org.onosproject.net.topology.Topology; -import org.onosproject.net.topology.TopologyService; import org.onosproject.net.topology.TopologyServiceAdapter; import java.util.HashMap; @@ -137,7 +135,7 @@ public class PathManagerTest { } // Fake entity to give out paths. - private class FakeTopoMgr extends TopologyServiceAdapter implements TopologyService { + private class FakeTopoMgr extends TopologyServiceAdapter { Set<Path> paths = new HashSet<>(); @Override @@ -152,7 +150,7 @@ public class PathManagerTest { } // Fake entity to give out hosts. - private class FakeHostMgr extends HostServiceAdapter implements HostService { + private class FakeHostMgr extends HostServiceAdapter { private Map<HostId, Host> hosts = new HashMap<>(); @Override diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/TopologyManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/TopologyManagerTest.java index f3cd28df..56133a0f 100644 --- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/TopologyManagerTest.java +++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/topology/impl/TopologyManagerTest.java @@ -114,7 +114,7 @@ public class TopologyManagerTest { link("c", 2, "d", 1), link("d", 1, "c", 2), link("d", 2, "a", 2), link("a", 2, "d", 2), link("e", 1, "f", 1), link("f", 1, "e", 1)); - GraphDescription data = new DefaultGraphDescription(4321L, devices, links); + GraphDescription data = new DefaultGraphDescription(4321L, System.currentTimeMillis(), devices, links); providerService.topologyChanged(data, null); } diff --git a/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/badComponent.json b/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/badComponent.json new file mode 100644 index 00000000..5c0ac35d --- /dev/null +++ b/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/badComponent.json @@ -0,0 +1,5 @@ +{ + "org.onosproject.proxyarp.ProxyArp2": { + "testProperty": true + } +}
\ No newline at end of file diff --git a/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/badConfig.json b/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/badConfig.json new file mode 100644 index 00000000..a76552e5 --- /dev/null +++ b/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/badConfig.json @@ -0,0 +1,5 @@ +{ + "fooComponent": { + badconfig + } +}
\ No newline at end of file diff --git a/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/basic.json b/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/basic.json new file mode 100644 index 00000000..dd329243 --- /dev/null +++ b/framework/src/onos/core/net/src/test/resources/org/onosproject/cfg/impl/basic.json @@ -0,0 +1,5 @@ +{ + "fooComponent": { + "testProperty": true + } +}
\ No newline at end of file |