From 13d05bc8458758ee39cb829098241e89616717ee Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Wed, 9 Sep 2015 22:15:21 -0700 Subject: ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60 Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd --- framework/src/onos/incubator/net/pom.xml | 101 ++++++ .../net/config/impl/ExtraNetworkConfigs.java | 69 ++++ .../incubator/net/config/impl/package-info.java | 20 ++ .../net/domain/impl/IntentDomainManager.java | 210 ++++++++++++ .../incubator/net/domain/impl/package-info.java | 20 ++ .../incubator/net/impl/PortStatisticsManager.java | 162 +++++++++ .../incubator/net/impl/package-info.java | 20 ++ .../incubator/net/intf/impl/InterfaceManager.java | 184 +++++++++++ .../incubator/net/meter/impl/MeterManager.java | 233 +++++++++++++ .../resource/label/impl/LabelResourceManager.java | 221 +++++++++++++ .../net/resource/label/impl/package-info.java | 20 ++ .../incubator/net/tunnel/impl/TunnelManager.java | 366 +++++++++++++++++++++ .../incubator/net/tunnel/impl/package-info.java | 20 ++ .../incubator/net/meter/impl/MeterManagerTest.java | 234 +++++++++++++ .../net/src/test/resources/domain-config.json | 36 ++ .../src/test/resources/fractal-domain-config.json | 28 ++ 16 files changed, 1944 insertions(+) create mode 100644 framework/src/onos/incubator/net/pom.xml create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/ExtraNetworkConfigs.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/package-info.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/IntentDomainManager.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/package-info.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/PortStatisticsManager.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/package-info.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/package-info.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/TunnelManager.java create mode 100644 framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/package-info.java create mode 100644 framework/src/onos/incubator/net/src/test/java/org/onosproject/incubator/net/meter/impl/MeterManagerTest.java create mode 100644 framework/src/onos/incubator/net/src/test/resources/domain-config.json create mode 100644 framework/src/onos/incubator/net/src/test/resources/fractal-domain-config.json (limited to 'framework/src/onos/incubator/net') diff --git a/framework/src/onos/incubator/net/pom.xml b/framework/src/onos/incubator/net/pom.xml new file mode 100644 index 00000000..a0b5391d --- /dev/null +++ b/framework/src/onos/incubator/net/pom.xml @@ -0,0 +1,101 @@ + + + + + 4.0.0 + + + org.onosproject + onos-incubator + 1.3.0-SNAPSHOT + ../pom.xml + + + onos-incubator-net + bundle + + ONOS incubating network control core subsystems + + + + org.onosproject + onos-incubator-api + ${project.version} + + + + org.onosproject + onos-core-common + ${project.version} + tests + test + + + + org.onosproject + onos-core-serializers + ${project.version} + tests + test + + + + org.onosproject + onos-core-common + + + + org.easymock + easymock + test + + + + org.apache.felix + org.apache.felix.scr.annotations + + + + org.apache.karaf.features + org.apache.karaf.features.core + + + + org.apache.karaf.system + org.apache.karaf.system.core + + + + org.onosproject + onos-incubator-store + ${project.version} + test + + + + + + + org.apache.felix + maven-scr-plugin + + + + + diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/ExtraNetworkConfigs.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/ExtraNetworkConfigs.java new file mode 100644 index 00000000..e77e1da0 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/ExtraNetworkConfigs.java @@ -0,0 +1,69 @@ +/* + * 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.incubator.net.config.impl; + +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.onosproject.incubator.net.domain.IntentDomainConfig; +import org.onosproject.incubator.net.domain.IntentDomainId; +import org.onosproject.net.config.ConfigFactory; +import org.onosproject.net.config.NetworkConfigRegistry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Set; + +import static org.onosproject.incubator.net.config.basics.ExtraSubjectFactories.INTENT_DOMAIN_SUBJECT_FACTORY; + +/** + * Component for registration of builtin basic network configurations. + */ +@Component(immediate = true) +public class ExtraNetworkConfigs { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final Set factories = ImmutableSet.of( + new ConfigFactory(INTENT_DOMAIN_SUBJECT_FACTORY, + IntentDomainConfig.class, + "basic") { + @Override + public IntentDomainConfig createConfig() { + return new IntentDomainConfig(); + } + } + ); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected NetworkConfigRegistry registry; + + @Activate + public void activate() { + factories.forEach(registry::registerConfigFactory); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + factories.forEach(registry::unregisterConfigFactory); + log.info("Stopped"); + } + +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/package-info.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/package-info.java new file mode 100644 index 00000000..a2375429 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/config/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of the network configuration subsystem. + */ +package org.onosproject.incubator.net.config.impl; \ No newline at end of file diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/IntentDomainManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/IntentDomainManager.java new file mode 100644 index 00000000..33c8a3c5 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/IntentDomainManager.java @@ -0,0 +1,210 @@ +/* + * 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.incubator.net.domain.impl; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; +import com.google.common.collect.Sets; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.graph.AdjacencyListsGraph; +import org.onlab.graph.Graph; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.config.NetworkConfigEvent; +import org.onosproject.net.config.NetworkConfigListener; +import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.incubator.net.domain.DomainEdge; +import org.onosproject.incubator.net.domain.DomainVertex; +import org.onosproject.incubator.net.domain.IntentDomain; +import org.onosproject.incubator.net.domain.IntentDomainAdminService; +import org.onosproject.incubator.net.domain.IntentDomainConfig; +import org.onosproject.incubator.net.domain.IntentDomainId; +import org.onosproject.incubator.net.domain.IntentDomainListener; +import org.onosproject.incubator.net.domain.IntentDomainProvider; +import org.onosproject.incubator.net.domain.IntentDomainService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + +/** + * Implementation of the intent domain service. + */ +@Component(immediate = true) +@Service +public class IntentDomainManager + implements IntentDomainService, IntentDomainAdminService { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected NetworkConfigService configService; + + private NetworkConfigListener cfgListener = new InternalConfigListener(); + + private final ConcurrentMap domains = Maps.newConcurrentMap(); + + private final Multimap appToDomain = + Multimaps.synchronizedSetMultimap(HashMultimap.create()); + + private Graph graph; + + @Activate + protected void activate() { + configService.addListener(cfgListener); + configService.getSubjects(IntentDomainId.class, IntentDomainConfig.class) + .forEach(this::processConfig); + graph = buildGraph(); + log.debug("Graph: {}", graph); + log.info("Started"); + } + + private void processConfig(IntentDomainId intentDomainId) { + IntentDomainConfig cfg = configService.getConfig(intentDomainId, + IntentDomainConfig.class); + + domains.put(intentDomainId, createDomain(intentDomainId, cfg)); + appToDomain.put(cfg.applicationName(), intentDomainId); + } + + private IntentDomain createDomain(IntentDomainId id, IntentDomainConfig cfg) { + return new IntentDomain(id, cfg.domainName(), cfg.internalDevices(), cfg.edgePorts()); + } + + private Graph buildGraph() { + Set vertices = Sets.newHashSet(); + Set edges = Sets.newHashSet(); + + Map deviceVertices = Maps.newHashMap(); + domains.forEach((id, domain) -> { + DomainVertex domainVertex = new DomainVertex(id); + + // Add vertex for domain + vertices.add(domainVertex); + + // Add vertices for connection devices + domain.edgePorts().stream() + .map(ConnectPoint::deviceId) + .collect(Collectors.toSet()) + .forEach(did -> deviceVertices.putIfAbsent(did, new DomainVertex(did))); + + // Add bi-directional edges between each domain and connection device + domain.edgePorts().forEach(cp -> { + DomainVertex deviceVertex = deviceVertices.get(cp.deviceId()); + edges.add(new DomainEdge(domainVertex, deviceVertex, cp)); + edges.add(new DomainEdge(deviceVertex, domainVertex, cp)); + }); + }); + + vertices.addAll(deviceVertices.values()); + //FIXME verify graph integrity... + return new AdjacencyListsGraph<>(vertices, edges); + } + + @Deactivate + protected void deactivate() { + configService.removeListener(cfgListener); + log.info("Stopped"); + } + + @Override + public IntentDomain getDomain(IntentDomainId id) { + return domains.get(id); + } + + @Override + public Set getDomains() { + return ImmutableSet.copyOf(domains.values()); + } + + @Override + public Set getDomains(DeviceId deviceId) { + return domains.values().stream() + .filter(domain -> + domain.internalDevices().contains(deviceId) || + domain.edgePorts().stream() + .map(ConnectPoint::deviceId) + .anyMatch(d -> d.equals(deviceId))) + .collect(Collectors.toSet()); + } + + @Override + public Graph getDomainGraph() { + return graph; + } + + @Override + public void addListener(IntentDomainListener listener) { + //TODO slide in AbstractListenerManager + } + + @Override + public void removeListener(IntentDomainListener listener) { + //TODO slide in AbstractListenerManager + } + + @Override + public void registerApplication(ApplicationId applicationId, IntentDomainProvider provider) { + appToDomain.get(applicationId.name()).forEach(d -> domains.get(d).setProvider(provider)); + } + + @Override + public void unregisterApplication(ApplicationId applicationId) { + appToDomain.get(applicationId.name()).forEach(d -> domains.get(d).unsetProvider()); + } + + private class InternalConfigListener implements NetworkConfigListener { + @Override + public void event(NetworkConfigEvent event) { + switch (event.type()) { + case CONFIG_ADDED: + case CONFIG_UPDATED: + processConfig((IntentDomainId) event.subject()); + graph = buildGraph(); + log.debug("Graph: {}", graph); + break; + + case CONFIG_REGISTERED: + case CONFIG_UNREGISTERED: + case CONFIG_REMOVED: + default: + //TODO + break; + } + } + + @Override + public boolean isRelevant(NetworkConfigEvent event) { + return event.configClass().equals(IntentDomainConfig.class); + } + } +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/package-info.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/package-info.java new file mode 100644 index 00000000..8fe3a3c6 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/domain/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of the intent domain subsystem. + */ +package org.onosproject.incubator.net.domain.impl; \ No newline at end of file diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/PortStatisticsManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/PortStatisticsManager.java new file mode 100644 index 00000000..1a615481 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/PortStatisticsManager.java @@ -0,0 +1,162 @@ +/* + * 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.incubator.net.impl; + +import com.google.common.collect.Maps; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.incubator.net.PortStatisticsService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceListener; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.device.PortStatistics; +import org.onosproject.net.statistic.DefaultLoad; +import org.onosproject.net.statistic.Load; +import org.slf4j.Logger; + +import java.util.Map; +import java.util.stream.Collectors; + +import static org.onosproject.net.PortNumber.portNumber; +import static org.onosproject.net.device.DeviceEvent.Type.*; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Implementation of the port statistics service. + */ +@Component(immediate = true) +@Service +public class PortStatisticsManager implements PortStatisticsService { + + private final Logger log = getLogger(getClass()); + + private static final long POLL_FREQUENCY = 10_000; // milliseconds + private static final long STALE_LIMIT = (long) (1.5 * POLL_FREQUENCY); + private static final int SECOND = 1_000; // milliseconds + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + private final DeviceListener deviceListener = new InternalDeviceListener(); + + private Map current = Maps.newConcurrentMap(); + private Map previous = Maps.newConcurrentMap(); + + @Activate + public void activate() { + deviceService.addListener(deviceListener); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + deviceService.removeListener(deviceListener); + log.info("Stopped"); + } + + @Override + public Load load(ConnectPoint connectPoint) { + DataPoint c = current.get(connectPoint); + DataPoint p = previous.get(connectPoint); + long now = System.currentTimeMillis(); + + if (c != null && p != null && (now - c.time < STALE_LIMIT)) { + if (c.time > p.time + SECOND) { + //Use max of either Tx or Rx load as the total load of a port + Load load = null; + if (c.stats.bytesSent() >= p.stats.bytesSent()) { + load = new DefaultLoad(c.stats.bytesSent(), p.stats.bytesSent(), + (int) (c.time - p.time) / SECOND); + } + if (c.stats.bytesReceived() >= p.stats.bytesReceived()) { + Load rcvLoad = new DefaultLoad(c.stats.bytesReceived(), p.stats.bytesReceived(), + (int) (c.time - p.time) / SECOND); + load = ((load == null) || (rcvLoad.rate() > load.rate())) ? rcvLoad : load; + } + return load; + } + } + return null; + } + + // Monitors port stats update messages. + private class InternalDeviceListener implements DeviceListener { + @Override + public void event(DeviceEvent event) { + DeviceEvent.Type type = event.type(); + DeviceId deviceId = event.subject().id(); + if (type == PORT_STATS_UPDATED) { + // Update port load + updateDeviceData(deviceId); + + } else if (type == DEVICE_REMOVED || + (type == DEVICE_AVAILABILITY_CHANGED && + !deviceService.isAvailable(deviceId))) { + // Clean-up all port loads + pruneDeviceData(deviceId); + } + } + } + + // Updates the port stats for the specified device + private void updateDeviceData(DeviceId deviceId) { + deviceService.getPortStatistics(deviceId) + .forEach(stats -> updatePortData(deviceId, stats)); + } + + // Updates the port stats for the specified port + private void updatePortData(DeviceId deviceId, PortStatistics stats) { + ConnectPoint cp = new ConnectPoint(deviceId, portNumber(stats.port())); + DataPoint c = current.get(cp); + + // Create a new data point and make it the current one + current.put(cp, new DataPoint(stats)); + + // If we have a current data point, demote it to previous + if (c != null) { + previous.put(cp, c); + } + } + + // Cleans all port loads for the specified device + private void pruneDeviceData(DeviceId deviceId) { + pruneMap(current, deviceId); + pruneMap(previous, deviceId); + } + + private void pruneMap(Map map, DeviceId deviceId) { + map.keySet().stream().filter(cp -> deviceId.equals(cp.deviceId())) + .collect(Collectors.toSet()).forEach(map::remove); + } + + // Auxiliary data point to track when we receive different samples. + private class DataPoint { + long time; + PortStatistics stats; + + DataPoint(PortStatistics stats) { + time = System.currentTimeMillis(); + this.stats = stats; + } + } + +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/package-info.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/package-info.java new file mode 100644 index 00000000..842a58fb --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementations of incubating core subsystems. + */ +package org.onosproject.incubator.net.impl; \ No newline at end of file diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java new file mode 100644 index 00000000..f82cdbf2 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java @@ -0,0 +1,184 @@ +/* + * 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.incubator.net.intf.impl; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.IpAddress; +import org.onlab.packet.VlanId; +import org.onosproject.incubator.net.config.basics.ConfigException; +import org.onosproject.incubator.net.config.basics.InterfaceConfig; +import org.onosproject.incubator.net.intf.Interface; +import org.onosproject.incubator.net.intf.InterfaceService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.config.NetworkConfigEvent; +import org.onosproject.net.config.NetworkConfigListener; +import org.onosproject.net.config.NetworkConfigService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.toSet; + +/** + * Manages the inventory of interfaces in the system. + */ +@Service +@Component(immediate = true) +public class InterfaceManager implements InterfaceService { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private static final Class SUBJECT_CLASS = ConnectPoint.class; + private static final Class CONFIG_CLASS = InterfaceConfig.class; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected NetworkConfigService configService; + + private final InternalConfigListener listener = new InternalConfigListener(); + + private final Map> interfaces = Maps.newConcurrentMap(); + + @Activate + public void activate() { + configService.addListener(listener); + + // TODO address concurrency issues here + for (ConnectPoint subject : configService.getSubjects(SUBJECT_CLASS, CONFIG_CLASS)) { + InterfaceConfig config = configService.getConfig(subject, CONFIG_CLASS); + + if (config != null) { + updateInterfaces(config); + } + } + + log.info("Started"); + } + + @Deactivate + public void deactivate() { + configService.removeListener(listener); + + log.info("Stopped"); + } + + @Override + public Set getInterfaces() { + return interfaces.values() + .stream() + .flatMap(set -> set.stream()) + .collect(collectingAndThen(toSet(), ImmutableSet::copyOf)); + } + + @Override + public Set getInterfacesByPort(ConnectPoint port) { + Set intfs = interfaces.get(port); + if (intfs == null) { + return Collections.emptySet(); + } + return ImmutableSet.copyOf(intfs); + } + + @Override + public Set getInterfacesByIp(IpAddress ip) { + return interfaces.values() + .stream() + .flatMap(set -> set.stream()) + .filter(intf -> intf.ipAddresses() + .stream() + .anyMatch(ia -> ia.ipAddress().equals(ip))) + .collect(collectingAndThen(toSet(), ImmutableSet::copyOf)); + } + + @Override + public Interface getMatchingInterface(IpAddress ip) { + Optional match = interfaces.values() + .stream() + .flatMap(set -> set.stream()) + .filter(intf -> intf.ipAddresses() + .stream() + .anyMatch(intfIp -> intfIp.subnetAddress().contains(ip))) + .findFirst(); + + if (match.isPresent()) { + return match.get(); + } + + return null; + } + + @Override + public Set getInterfacesByVlan(VlanId vlan) { + return interfaces.values() + .stream() + .flatMap(set -> set.stream()) + .filter(intf -> intf.vlan().equals(vlan)) + .collect(collectingAndThen(toSet(), ImmutableSet::copyOf)); + } + + private void updateInterfaces(InterfaceConfig intfConfig) { + try { + interfaces.put(intfConfig.subject(), intfConfig.getInterfaces()); + } catch (ConfigException e) { + log.error("Error in interface config", e); + } + } + + private void removeInterfaces(ConnectPoint port) { + interfaces.remove(port); + } + + /** + * Listener for network config events. + */ + private class InternalConfigListener implements NetworkConfigListener { + + @Override + public void event(NetworkConfigEvent event) { + switch (event.type()) { + case CONFIG_ADDED: + case CONFIG_UPDATED: + if (event.configClass() == InterfaceConfig.class) { + InterfaceConfig config = + configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class); + updateInterfaces(config); + } + break; + case CONFIG_REMOVED: + if (event.configClass() == InterfaceConfig.class) { + removeInterfaces((ConnectPoint) event.subject()); + } + break; + case CONFIG_REGISTERED: + case CONFIG_UNREGISTERED: + default: + break; + } + } + } +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java new file mode 100644 index 00000000..575a7153 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/meter/impl/MeterManager.java @@ -0,0 +1,233 @@ +/* + * 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.incubator.net.meter.impl; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.util.TriConsumer; +import org.onosproject.net.meter.DefaultMeter; +import org.onosproject.net.meter.Meter; +import org.onosproject.net.meter.MeterEvent; +import org.onosproject.net.meter.MeterFailReason; +import org.onosproject.net.meter.MeterId; +import org.onosproject.net.meter.MeterListener; +import org.onosproject.net.meter.MeterOperation; +import org.onosproject.net.meter.MeterProvider; +import org.onosproject.net.meter.MeterProviderRegistry; +import org.onosproject.net.meter.MeterProviderService; +import org.onosproject.net.meter.MeterRequest; +import org.onosproject.net.meter.MeterService; +import org.onosproject.net.meter.MeterState; +import org.onosproject.net.meter.MeterStore; +import org.onosproject.net.meter.MeterStoreDelegate; +import org.onosproject.net.meter.MeterStoreResult; +import org.onosproject.net.DeviceId; +import org.onosproject.net.provider.AbstractListenerProviderRegistry; +import org.onosproject.net.provider.AbstractProviderService; +import org.onosproject.store.service.AtomicCounter; +import org.onosproject.store.service.StorageService; +import org.slf4j.Logger; + +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.slf4j.LoggerFactory.getLogger; + + +/** + * Provides implementation of the meter service APIs. + */ +@Component(immediate = true, enabled = true) +@Service +public class MeterManager extends AbstractListenerProviderRegistry + implements MeterService, MeterProviderRegistry { + + private final String meterIdentifier = "meter-id-counter"; + private final Logger log = getLogger(getClass()); + private final MeterStoreDelegate delegate = new InternalMeterStoreDelegate(); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected StorageService storageService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected MeterStore store; + + private AtomicCounter meterIdCounter; + + private TriConsumer onComplete; + + @Activate + public void activate() { + meterIdCounter = storageService.atomicCounterBuilder() + .withName(meterIdentifier) + .build(); + + store.setDelegate(delegate); + + onComplete = (request, result, error) -> + { + request.context().ifPresent(c -> { + if (error != null) { + c.onError(request, MeterFailReason.UNKNOWN); + } else { + if (result.reason().isPresent()) { + c.onError(request, result.reason().get()); + } else { + c.onSuccess(request); + } + } + }); + + }; + log.info("Started"); + } + + @Deactivate + public void deactivate() { + store.unsetDelegate(delegate); + log.info("Stopped"); + } + + @Override + protected MeterProviderService createProviderService(MeterProvider provider) { + return new InternalMeterProviderService(provider); + } + + @Override + public Meter submit(MeterRequest request) { + + Meter.Builder mBuilder = DefaultMeter.builder() + .forDevice(request.deviceId()) + .fromApp(request.appId()) + .withBands(request.bands()) + .withId(allocateMeterId()) + .withUnit(request.unit()); + + if (request.isBurst()) { + mBuilder.burst(); + } + DefaultMeter m = (DefaultMeter) mBuilder.build(); + m.setState(MeterState.PENDING_ADD); + store.storeMeter(m).whenComplete((result, error) -> + onComplete.accept(request, result, error)); + return m; + } + + @Override + public void withdraw(MeterRequest request, MeterId meterId) { + Meter.Builder mBuilder = DefaultMeter.builder() + .forDevice(request.deviceId()) + .fromApp(request.appId()) + .withBands(request.bands()) + .withId(meterId) + .withUnit(request.unit()); + + if (request.isBurst()) { + mBuilder.burst(); + } + + DefaultMeter m = (DefaultMeter) mBuilder.build(); + m.setState(MeterState.PENDING_REMOVE); + store.deleteMeter(m).whenComplete((result, error) -> + onComplete.accept(request, result, error)); + } + + @Override + public Meter getMeter(MeterId id) { + return store.getMeter(id); + } + + @Override + public Collection getAllMeters() { + return store.getAllMeters(); + } + + private MeterId allocateMeterId() { + // FIXME: This will break one day. + return MeterId.meterId((int) meterIdCounter.incrementAndGet()); + } + + private class InternalMeterProviderService + extends AbstractProviderService + implements MeterProviderService { + + /** + * Creates a provider service on behalf of the specified provider. + * + * @param provider provider to which this service is being issued + */ + protected InternalMeterProviderService(MeterProvider provider) { + super(provider); + } + + @Override + public void meterOperationFailed(MeterOperation operation, + MeterFailReason reason) { + store.failedMeter(operation, reason); + } + + @Override + public void pushMeterMetrics(DeviceId deviceId, Collection meterEntries) { + //FIXME: FOLLOWING CODE CANNOT BE TESTED UNTIL SOMETHING THAT + //FIXME: IMPLEMENTS METERS EXISTS + Map storedMeterMap = store.getAllMeters().stream() + .collect(Collectors.toMap(Meter::id, m -> m)); + + meterEntries.stream() + .filter(m -> storedMeterMap.remove(m.id()) != null) + .forEach(m -> store.updateMeterState(m)); + + storedMeterMap.values().stream().forEach(m -> { + if (m.state() == MeterState.PENDING_ADD) { + provider().performMeterOperation(m.deviceId(), + new MeterOperation(m, + MeterOperation.Type.ADD)); + } else { + store.deleteMeterNow(m); + } + }); + } + } + + private class InternalMeterStoreDelegate implements MeterStoreDelegate { + + @Override + public void notify(MeterEvent event) { + DeviceId deviceId = event.subject().deviceId(); + MeterProvider p = getProvider(event.subject().deviceId()); + switch (event.type()) { + case METER_ADD_REQ: + p.performMeterOperation(deviceId, new MeterOperation(event.subject(), + MeterOperation.Type.ADD)); + break; + case METER_REM_REQ: + p.performMeterOperation(deviceId, new MeterOperation(event.subject(), + MeterOperation.Type.REMOVE)); + break; + default: + log.warn("Unknown meter event {}", event.type()); + } + + } + } + +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java new file mode 100644 index 00000000..56167c48 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java @@ -0,0 +1,221 @@ +package org.onosproject.incubator.net.resource.label.impl; + +import com.google.common.collect.Multimap; +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.net.provider.AbstractListenerProviderRegistry; +import org.onosproject.incubator.net.resource.label.LabelResource; +import org.onosproject.incubator.net.resource.label.LabelResourceAdminService; +import org.onosproject.incubator.net.resource.label.LabelResourceDelegate; +import org.onosproject.incubator.net.resource.label.LabelResourceEvent; +import org.onosproject.incubator.net.resource.label.LabelResourceId; +import org.onosproject.incubator.net.resource.label.LabelResourceListener; +import org.onosproject.incubator.net.resource.label.LabelResourcePool; +import org.onosproject.incubator.net.resource.label.LabelResourceProvider; +import org.onosproject.incubator.net.resource.label.LabelResourceProviderRegistry; +import org.onosproject.incubator.net.resource.label.LabelResourceProviderService; +import org.onosproject.incubator.net.resource.label.LabelResourceService; +import org.onosproject.incubator.net.resource.label.LabelResourceStore; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceEvent.Type; +import org.onosproject.net.device.DeviceListener; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.provider.AbstractProviderService; +import org.slf4j.Logger; + +import java.util.Collection; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * provides implementation of the label resource NB & SB APIs. + * + */ +@Component(immediate = true) +@Service +public class LabelResourceManager + extends AbstractListenerProviderRegistry + implements LabelResourceService, LabelResourceAdminService, LabelResourceProviderRegistry { + private final Logger log = getLogger(getClass()); + private final LabelResourceDelegate delegate = new InternalLabelResourceDelegate(); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected LabelResourceStore store; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + private DeviceListener deviceListener = new InternalDeviceListener(); + + @Activate + public void activate() { + store.setDelegate(delegate); + eventDispatcher.addSink(LabelResourceEvent.class, listenerRegistry); + deviceService.addListener(deviceListener); + log.info("Started"); + + } + + @Deactivate + public void deactivate() { + deviceService.removeListener(deviceListener); + store.unsetDelegate(delegate); + eventDispatcher.removeSink(LabelResourceEvent.class); + log.info("Stopped"); + } + + @Override + public boolean createDevicePool(DeviceId deviceId, + LabelResourceId beginLabel, + LabelResourceId endLabel) { + checkNotNull(deviceId, "deviceId is not null"); + checkNotNull(beginLabel, "beginLabel is not null"); + checkNotNull(endLabel, "endLabel is not null"); + checkArgument(beginLabel.labelId() >= 0 || endLabel.labelId() >= 0, + "The value of beginLabel and the value of endLabel must be both positive number."); + checkArgument(beginLabel.labelId() < endLabel.labelId(), + "The value of endLabel must be greater than the value of beginLabel."); + return store.createDevicePool(deviceId, beginLabel, endLabel); + } + + @Override + public boolean createGlobalPool(LabelResourceId beginLabel, + LabelResourceId endLabel) { + checkNotNull(beginLabel, "beginLabel is not null"); + checkNotNull(endLabel, "endLabel is not null"); + checkArgument(beginLabel.labelId() >= 0 && endLabel.labelId() >= 0, + "The value of beginLabel and the value of endLabel must be both positive number."); + checkArgument(beginLabel.labelId() < endLabel.labelId(), + "The value of endLabel must be greater than the value of beginLabel."); + return store.createGlobalPool(beginLabel, endLabel); + } + + @Override + public boolean destroyDevicePool(DeviceId deviceId) { + checkNotNull(deviceId, "deviceId is not null"); + return store.destroyDevicePool(deviceId); + } + + @Override + public boolean destroyGlobalPool() { + return store.destroyGlobalPool(); + } + + @Override + public Collection applyFromDevicePool(DeviceId deviceId, + long applyNum) { + checkNotNull(deviceId, "deviceId is not null"); + checkNotNull(applyNum, "applyNum is not null"); + return store.applyFromDevicePool(deviceId, applyNum); + } + + @Override + public Collection applyFromGlobalPool(long applyNum) { + checkNotNull(applyNum, "applyNum is not null"); + return store.applyFromGlobalPool(applyNum); + } + + @Override + public boolean releaseToDevicePool(Multimap release) { + checkNotNull(release, "release is not null"); + return store.releaseToDevicePool(release); + } + + @Override + public boolean releaseToGlobalPool(Set release) { + checkNotNull(release, "release is not null"); + return store.releaseToGlobalPool(release); + } + + @Override + public boolean isDevicePoolFull(DeviceId deviceId) { + checkNotNull(deviceId, "deviceId is not null"); + return store.isDevicePoolFull(deviceId); + } + + @Override + public boolean isGlobalPoolFull() { + return store.isGlobalPoolFull(); + } + + @Override + public long getFreeNumOfDevicePool(DeviceId deviceId) { + checkNotNull(deviceId, "deviceId is not null"); + return store.getFreeNumOfDevicePool(deviceId); + } + + @Override + public long getFreeNumOfGlobalPool() { + return store.getFreeNumOfGlobalPool(); + } + + @Override + public LabelResourcePool getDeviceLabelResourcePool(DeviceId deviceId) { + checkNotNull(deviceId, "deviceId is not null"); + return store.getDeviceLabelResourcePool(deviceId); + } + + @Override + public LabelResourcePool getGlobalLabelResourcePool() { + return store.getGlobalLabelResourcePool(); + } + + private class InternalLabelResourceDelegate implements LabelResourceDelegate { + @Override + public void notify(LabelResourceEvent event) { + post(event); + } + + } + + private class InternalDeviceListener implements DeviceListener { + @Override + public void event(DeviceEvent event) { + Device device = event.subject(); + if (Type.DEVICE_REMOVED.equals(event.type())) { + destroyDevicePool(device.id()); + } + } + } + + private class InternalLabelResourceProviderService + extends AbstractProviderService + implements LabelResourceProviderService { + + protected InternalLabelResourceProviderService(LabelResourceProvider provider) { + super(provider); + } + + @Override + public void deviceLabelResourcePoolDetected(DeviceId deviceId, + LabelResourceId beginLabel, + LabelResourceId endLabel) { + checkNotNull(deviceId, "deviceId is not null"); + checkNotNull(beginLabel, "beginLabel is not null"); + checkNotNull(endLabel, "endLabel is not null"); + createDevicePool(deviceId, beginLabel, endLabel); + } + + @Override + public void deviceLabelResourcePoolDestroyed(DeviceId deviceId) { + checkNotNull(deviceId, "deviceId is not null"); + destroyDevicePool(deviceId); + } + + } + + @Override + protected LabelResourceProviderService createProviderService(LabelResourceProvider provider) { + return new InternalLabelResourceProviderService(provider); + } +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/package-info.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/package-info.java new file mode 100644 index 00000000..afd31b48 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementation of the label resource subsystem. + */ +package org.onosproject.incubator.net.resource.label.impl; \ No newline at end of file diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/TunnelManager.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/TunnelManager.java new file mode 100644 index 00000000..d316388f --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/TunnelManager.java @@ -0,0 +1,366 @@ +/* + * 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.incubator.net.tunnel.impl; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.net.provider.AbstractListenerProviderRegistry; +import org.onosproject.core.ApplicationId; +import org.onosproject.incubator.net.tunnel.DefaultTunnel; +import org.onosproject.incubator.net.tunnel.Tunnel; +import org.onosproject.incubator.net.tunnel.Tunnel.Type; +import org.onosproject.incubator.net.tunnel.TunnelAdminService; +import org.onosproject.incubator.net.tunnel.TunnelDescription; +import org.onosproject.incubator.net.tunnel.TunnelEndPoint; +import org.onosproject.incubator.net.tunnel.TunnelEvent; +import org.onosproject.incubator.net.tunnel.TunnelId; +import org.onosproject.incubator.net.tunnel.TunnelListener; +import org.onosproject.incubator.net.tunnel.TunnelName; +import org.onosproject.incubator.net.tunnel.TunnelProvider; +import org.onosproject.incubator.net.tunnel.TunnelProviderRegistry; +import org.onosproject.incubator.net.tunnel.TunnelProviderService; +import org.onosproject.incubator.net.tunnel.TunnelService; +import org.onosproject.incubator.net.tunnel.TunnelStore; +import org.onosproject.incubator.net.tunnel.TunnelStoreDelegate; +import org.onosproject.incubator.net.tunnel.TunnelSubscription; +import org.onosproject.net.Annotations; +import org.onosproject.net.DeviceId; +import org.onosproject.net.Path; +import org.onosproject.net.provider.AbstractProviderService; +import org.onosproject.net.provider.ProviderId; +import org.slf4j.Logger; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Provides implementation of the tunnel NB/SB APIs. + */ +@Component(immediate = true, enabled = true) +@Service +public class TunnelManager + extends AbstractListenerProviderRegistry + implements TunnelService, TunnelAdminService, TunnelProviderRegistry { + + private static final String TUNNNEL_ID_NULL = "Tunnel ID cannot be null"; + + private final Logger log = getLogger(getClass()); + + private final TunnelStoreDelegate delegate = new InternalStoreDelegate(); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected TunnelStore store; + + + @Activate + public void activate() { + store.setDelegate(delegate); + eventDispatcher.addSink(TunnelEvent.class, listenerRegistry); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + store.unsetDelegate(delegate); + eventDispatcher.removeSink(TunnelEvent.class); + log.info("Stopped"); + } + + @Override + public void removeTunnel(TunnelId tunnelId) { + checkNotNull(tunnelId, TUNNNEL_ID_NULL); + store.deleteTunnel(tunnelId); + Tunnel tunnel = store.queryTunnel(tunnelId); + if (tunnel.providerId() != null) { + TunnelProvider provider = getProvider(tunnel.providerId()); + if (provider != null) { + provider.releaseTunnel(tunnel); + } + } else { + Set ids = getProviders(); + for (ProviderId providerId : ids) { + TunnelProvider provider = getProvider(providerId); + provider.releaseTunnel(tunnel); + } + } + } + + @Override + public void updateTunnel(Tunnel tunnel, Path path) { + store.createOrUpdateTunnel(tunnel); + if (tunnel.providerId() != null) { + TunnelProvider provider = getProvider(tunnel.providerId()); + if (provider != null) { + provider.updateTunnel(tunnel, path); + } + } else { + Set ids = getProviders(); + for (ProviderId providerId : ids) { + TunnelProvider provider = getProvider(providerId); + provider.updateTunnel(tunnel, path); + } + } + } + + @Override + public void removeTunnels(TunnelEndPoint src, TunnelEndPoint dst, + ProviderId producerName) { + store.deleteTunnel(src, dst, producerName); + Collection setTunnels = store.queryTunnel(src, dst); + for (Tunnel tunnel : setTunnels) { + if (producerName != null + && !tunnel.providerId().equals(producerName)) { + continue; + } + if (tunnel.providerId() != null) { + TunnelProvider provider = getProvider(tunnel.providerId()); + if (provider != null) { + provider.releaseTunnel(tunnel); + } + } else { + Set ids = getProviders(); + for (ProviderId providerId : ids) { + TunnelProvider provider = getProvider(providerId); + provider.releaseTunnel(tunnel); + } + } + } + } + + @Override + public void removeTunnels(TunnelEndPoint src, TunnelEndPoint dst, Type type, + ProviderId producerName) { + store.deleteTunnel(src, dst, type, producerName); + Collection setTunnels = store.queryTunnel(src, dst); + for (Tunnel tunnel : setTunnels) { + if (producerName != null + && !tunnel.providerId().equals(producerName) + || !type.equals(tunnel.type())) { + continue; + } + if (tunnel.providerId() != null) { + TunnelProvider provider = getProvider(tunnel.providerId()); + if (provider != null) { + provider.releaseTunnel(tunnel); + } + } else { + Set ids = getProviders(); + for (ProviderId providerId : ids) { + TunnelProvider provider = getProvider(providerId); + provider.releaseTunnel(tunnel); + } + } + } + } + + @Override + public Tunnel borrowTunnel(ApplicationId consumerId, TunnelId tunnelId, + Annotations... annotations) { + return store.borrowTunnel(consumerId, tunnelId, annotations); + } + + @Override + public Collection borrowTunnel(ApplicationId consumerId, + TunnelName tunnelName, + Annotations... annotations) { + return store.borrowTunnel(consumerId, tunnelName, annotations); + } + + @Override + public Collection borrowTunnel(ApplicationId consumerId, + TunnelEndPoint src, TunnelEndPoint dst, + Annotations... annotations) { + Collection tunnels = store.borrowTunnel(consumerId, src, + dst, annotations); + if (tunnels == null || tunnels.size() == 0) { + Tunnel tunnel = new DefaultTunnel(null, src, dst, null, null, null, + null, null, annotations); + Set ids = getProviders(); + for (ProviderId providerId : ids) { + TunnelProvider provider = getProvider(providerId); + provider.setupTunnel(tunnel, null); + } + } + return tunnels; + } + + @Override + public Collection borrowTunnel(ApplicationId consumerId, + TunnelEndPoint src, TunnelEndPoint dst, + Type type, Annotations... annotations) { + Collection tunnels = store.borrowTunnel(consumerId, src, + dst, type, + annotations); + if (tunnels == null || tunnels.size() == 0) { + Tunnel tunnel = new DefaultTunnel(null, src, dst, type, null, null, + null, null, annotations); + Set ids = getProviders(); + for (ProviderId providerId : ids) { + TunnelProvider provider = getProvider(providerId); + provider.setupTunnel(tunnel, null); + } + } + return tunnels; + } + + @Override + public boolean returnTunnel(ApplicationId consumerId, + TunnelId tunnelId, Annotations... annotations) { + return store.returnTunnel(consumerId, tunnelId, annotations); + } + + @Override + public boolean returnTunnel(ApplicationId consumerId, + TunnelName tunnelName, + Annotations... annotations) { + return store.returnTunnel(consumerId, tunnelName, annotations); + } + + @Override + public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, + TunnelEndPoint dst, Type type, + Annotations... annotations) { + return store.returnTunnel(consumerId, src, dst, type, annotations); + } + + @Override + public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, + TunnelEndPoint dst, Annotations... annotations) { + return store.returnTunnel(consumerId, src, dst, annotations); + } + + @Override + public Tunnel queryTunnel(TunnelId tunnelId) { + return store.queryTunnel(tunnelId); + } + + @Override + public Collection queryTunnelSubscription(ApplicationId consumerId) { + return store.queryTunnelSubscription(consumerId); + } + + @Override + public Collection queryTunnel(Type type) { + return store.queryTunnel(type); + } + + @Override + public Collection queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) { + return store.queryTunnel(src, dst); + } + + + @Override + public Collection queryAllTunnels() { + return store.queryAllTunnels(); + } + + @Override + public int tunnelCount() { + return store.tunnelCount(); + } + + @Override + protected TunnelProviderService createProviderService(TunnelProvider provider) { + return new InternalTunnelProviderService(provider); + } + + private class InternalTunnelProviderService + extends AbstractProviderService + implements TunnelProviderService { + protected InternalTunnelProviderService(TunnelProvider provider) { + super(provider); + } + + + @Override + public TunnelId tunnelAdded(TunnelDescription tunnel) { + Tunnel storedTunnel = new DefaultTunnel(provider().id(), + tunnel.src(), tunnel.dst(), + tunnel.type(), + tunnel.groupId(), + tunnel.id(), + tunnel.tunnelName(), + tunnel.path(), + tunnel.annotations()); + return store.createOrUpdateTunnel(storedTunnel); + } + + @Override + public void tunnelUpdated(TunnelDescription tunnel) { + Tunnel storedTunnel = new DefaultTunnel(provider().id(), + tunnel.src(), tunnel.dst(), + tunnel.type(), + tunnel.groupId(), + tunnel.id(), + tunnel.tunnelName(), + tunnel.path(), + tunnel.annotations()); + store.createOrUpdateTunnel(storedTunnel); + } + + @Override + public void tunnelRemoved(TunnelDescription tunnel) { + if (tunnel.id() != null) { + store.deleteTunnel(tunnel.id()); + return; + } + if (tunnel.src() != null && tunnel.dst() != null + && tunnel.type() != null) { + store.deleteTunnel(tunnel.src(), tunnel.dst(), tunnel.type(), + provider().id()); + return; + } + if (tunnel.src() != null && tunnel.dst() != null + && tunnel.type() == null) { + store.deleteTunnel(tunnel.src(), tunnel.dst(), provider().id()); + return; + } + } + + + @Override + public Tunnel tunnelQueryById(TunnelId tunnelId) { + return store.queryTunnel(tunnelId); + } + + + } + + private class InternalStoreDelegate implements TunnelStoreDelegate { + @Override + public void notify(TunnelEvent event) { + if (event != null) { + post(event); + } + } + } + + @Override + public Iterable getTunnels(DeviceId deviceId) { + return Collections.emptyList(); + } + +} diff --git a/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/package-info.java b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/package-info.java new file mode 100644 index 00000000..6e0de551 --- /dev/null +++ b/framework/src/onos/incubator/net/src/main/java/org/onosproject/incubator/net/tunnel/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Core subsystem for tracking global inventory of tunnels. + */ +package org.onosproject.incubator.net.tunnel.impl; diff --git a/framework/src/onos/incubator/net/src/test/java/org/onosproject/incubator/net/meter/impl/MeterManagerTest.java b/framework/src/onos/incubator/net/src/test/java/org/onosproject/incubator/net/meter/impl/MeterManagerTest.java new file mode 100644 index 00000000..e0c0c868 --- /dev/null +++ b/framework/src/onos/incubator/net/src/test/java/org/onosproject/incubator/net/meter/impl/MeterManagerTest.java @@ -0,0 +1,234 @@ +/* + * 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.incubator.net.meter.impl; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.junit.TestUtils; +import org.onlab.packet.IpAddress; +import org.onosproject.cluster.ClusterServiceAdapter; +import org.onosproject.cluster.ControllerNode; +import org.onosproject.cluster.DefaultControllerNode; +import org.onosproject.cluster.NodeId; +import org.onosproject.common.event.impl.TestEventDispatcher; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.DefaultApplicationId; +import org.onosproject.incubator.store.meter.impl.DistributedMeterStore; +import org.onosproject.mastership.MastershipServiceAdapter; +import org.onosproject.net.DeviceId; +import org.onosproject.net.meter.Band; +import org.onosproject.net.meter.DefaultBand; +import org.onosproject.net.meter.DefaultMeter; +import org.onosproject.net.meter.DefaultMeterRequest; +import org.onosproject.net.meter.Meter; +import org.onosproject.net.meter.MeterId; +import org.onosproject.net.meter.MeterOperation; +import org.onosproject.net.meter.MeterOperations; +import org.onosproject.net.meter.MeterProvider; +import org.onosproject.net.meter.MeterProviderRegistry; +import org.onosproject.net.meter.MeterProviderService; +import org.onosproject.net.meter.MeterRequest; +import org.onosproject.net.meter.MeterService; +import org.onosproject.net.meter.MeterState; +import org.onosproject.net.provider.AbstractProvider; +import org.onosproject.net.provider.ProviderId; +import org.onosproject.store.service.TestStorageService; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.onosproject.net.NetTestTools.APP_ID; +import static org.onosproject.net.NetTestTools.did; +import static org.onosproject.net.NetTestTools.injectEventDispatcher; + +/** + * Meter manager tests. + */ +public class MeterManagerTest { + + private static final ProviderId PID = new ProviderId("of", "foo"); + private static final NodeId NID_LOCAL = new NodeId("local"); + private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1"); + + private MeterService service; + private MeterManager manager; + private DistributedMeterStore meterStore; + private MeterProviderRegistry registry; + private MeterProviderService providerService; + + private TestProvider provider; + + private ApplicationId appId; + + + private Meter m1; + private Meter m2; + private MeterRequest.Builder m1Request; + private MeterRequest.Builder m2Request; + + private Map meters = Maps.newHashMap(); + + @Before + public void setup() throws Exception { + meterStore = new DistributedMeterStore(); + TestUtils.setField(meterStore, "storageService", new TestStorageService()); + TestUtils.setField(meterStore, "clusterService", new TestClusterService()); + TestUtils.setField(meterStore, "mastershipService", new TestMastershipService()); + meterStore.activate(); + + manager = new MeterManager(); + manager.store = meterStore; + TestUtils.setField(manager, "storageService", new TestStorageService()); + injectEventDispatcher(manager, new TestEventDispatcher()); + service = manager; + registry = manager; + + manager.activate(); + + provider = new TestProvider(PID); + providerService = registry.register(provider); + + appId = new TestApplicationId(0, "MeterManagerTest"); + + assertTrue("provider should be registered", + registry.getProviders().contains(provider.id())); + + Band band = DefaultBand.builder() + .ofType(Band.Type.DROP) + .withRate(500) + .build(); + + m1 = DefaultMeter.builder() + .forDevice(did("1")) + .fromApp(APP_ID) + .withId(MeterId.meterId(1)) + .withUnit(Meter.Unit.KB_PER_SEC) + .withBands(Collections.singletonList(band)) + .build(); + + m2 = DefaultMeter.builder() + .forDevice(did("2")) + .fromApp(APP_ID) + .withId(MeterId.meterId(2)) + .withUnit(Meter.Unit.KB_PER_SEC) + .withBands(Collections.singletonList(band)) + .build(); + + m1Request = DefaultMeterRequest.builder() + .forDevice(did("1")) + .fromApp(APP_ID) + .withUnit(Meter.Unit.KB_PER_SEC) + .withBands(Collections.singletonList(band)); + + m2Request = DefaultMeterRequest.builder() + .forDevice(did("2")) + .fromApp(APP_ID) + .withUnit(Meter.Unit.KB_PER_SEC) + .withBands(Collections.singletonList(band)); + + + } + + @After + public void tearDown() { + registry.unregister(provider); + assertFalse("provider should not be registered", + registry.getProviders().contains(provider.id())); + + manager.deactivate(); + injectEventDispatcher(manager, null); + + } + + @Test + public void testAddition() { + manager.submit(m1Request.add()); + + assertTrue("The meter was not added", manager.getAllMeters().size() == 1); + + assertThat(manager.getMeter(MeterId.meterId(1)), is(m1)); + } + + @Test + public void testRemove() { + manager.submit(m1Request.add()); + manager.withdraw(m1Request.remove(), m1.id()); + + assertThat(manager.getMeter(MeterId.meterId(1)).state(), + is(MeterState.PENDING_REMOVE)); + + providerService.pushMeterMetrics(m1.deviceId(), Collections.emptyList()); + + assertTrue("The meter was not removed", manager.getAllMeters().size() == 0); + + } + + + + public class TestApplicationId extends DefaultApplicationId { + public TestApplicationId(int id, String name) { + super(id, name); + } + } + + private class TestProvider extends AbstractProvider implements MeterProvider { + + protected TestProvider(ProviderId id) { + super(PID); + } + + @Override + public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) { + //Currently unused. + } + + @Override + public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) { + meters.put(meterOp.meter().id(), meterOp.meter()); + } + } + + private final class TestClusterService extends ClusterServiceAdapter { + + ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST); + + @Override + public ControllerNode getLocalNode() { + return local; + } + + @Override + public Set getNodes() { + return Sets.newHashSet(); + } + + } + + private class TestMastershipService extends MastershipServiceAdapter { + @Override + public NodeId getMasterFor(DeviceId deviceId) { + return NID_LOCAL; + } + } +} diff --git a/framework/src/onos/incubator/net/src/test/resources/domain-config.json b/framework/src/onos/incubator/net/src/test/resources/domain-config.json new file mode 100644 index 00000000..beda11aa --- /dev/null +++ b/framework/src/onos/incubator/net/src/test/resources/domain-config.json @@ -0,0 +1,36 @@ +{ + "domains" : { + "cord" : { + "basic" : { + "name" : "Core Fabric", + "applicationName" : "org.onosproject.testdomain", + "internalDevices" : [ "of:1" ], + "edgePorts" : [ "of:12/1", "of:14/1" ] + } + }, + "mpls" : { + "basic" : { + "name" : "MPLS Core", + "applicationName" : "org.onosproject.testdomain", + "internalDevices" : [ "of:2" ], + "edgePorts" : [ "of:12/2", "of:23/2" ] + } + }, + "dc" : { + "basic" : { + "name" : "Data Center Fabric", + "applicationName" : "org.onosproject.testdomain", + "internalDevices" : [ "of:3" ], + "edgePorts" : [ "of:23/3", "of:34/3" ] + } + }, + "optical" : { + "basic" : { + "name" : "Optical Core", + "applicationName" : "org.onosproject.testdomain", + "internalDevices" : [ "of:4" ], + "edgePorts" : [ "of:14/4", "of:34/4" ] + } + } + } +} \ No newline at end of file diff --git a/framework/src/onos/incubator/net/src/test/resources/fractal-domain-config.json b/framework/src/onos/incubator/net/src/test/resources/fractal-domain-config.json new file mode 100644 index 00000000..521c840b --- /dev/null +++ b/framework/src/onos/incubator/net/src/test/resources/fractal-domain-config.json @@ -0,0 +1,28 @@ +{ + "domains" : { + "domain1" : { + "basic" : { + "name" : "Domain 1", + "applicationName" : "org.onosproject.meshdomain", + "internalDevices" : [ "of:0000000000001001", "of:0000000000001002", "of:0000000000001003" ], + "edgePorts" : [ "of:0000000000010000/1", "of:0000000003010000/2", "of:0000000002010000/1" ] + } + }, + "domain2" : { + "basic" : { + "name" : "Domain 2", + "applicationName" : "org.onosproject.meshdomain", + "internalDevices" : [ "of:0000000000002001", "of:0000000000002002", "of:0000000000002003" ], + "edgePorts" : [ "of:0000000000020000/1", "of:0000000003020000/1", "of:0000000002010000/2" ] + } + }, + "domain3" : { + "basic" : { + "name" : "Domain 3", + "applicationName" : "org.onosproject.meshdomain", + "internalDevices" : [ "of:0000000000003001", "of:0000000000003002", "of:0000000000003003" ], + "edgePorts" : [ "of:0000000000030000/1", "of:0000000003010000/1", "of:0000000003020000/2" ] + } + } + } +} \ No newline at end of file -- cgit 1.2.3-korg