ACTN TE Topology APP Implementation. Function of the implementation:
- receives multiple TE topologies from SB provider, and merge into one native TE topology
- store both original, received TE topologies and the native topology in TE topology data store
- provide APIs for NB APP to retreive and display the TE topologies.
Change-Id: Id0b2f3433966694fcf197cc0b8ad19a063e92f36
diff --git a/apps/tetopology/BUCK b/apps/tetopology/BUCK
index 8a74315..4fdc805 100644
--- a/apps/tetopology/BUCK
+++ b/apps/tetopology/BUCK
@@ -1,5 +1,7 @@
COMPILE_DEPS = [
'//lib:CORE_DEPS',
+ '//incubator/api:onos-incubator-api',
+ '//core/store/serializers:onos-core-serializers',
]
osgi_jar_with_tests (
diff --git a/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
new file mode 100644
index 0000000..f177709
--- /dev/null
+++ b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2016 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.tetopology.management.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.List;
+import java.lang.annotation.ElementType;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Map;
+
+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.util.KryoNamespace;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.MapEvent;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.Networks;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+import org.onosproject.tetopology.management.api.TeTopologyType;
+import org.onosproject.tetopology.management.api.link.AsNumber;
+import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
+import org.onosproject.tetopology.management.api.link.ExternalDomain;
+import org.onosproject.tetopology.management.api.link.TeIpv4;
+import org.onosproject.tetopology.management.api.link.TeIpv6;
+import org.onosproject.tetopology.management.api.link.Label;
+import org.onosproject.tetopology.management.api.link.LinkProtectionType;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.link.PathElement;
+import org.onosproject.tetopology.management.api.link.TeLink;
+import org.onosproject.tetopology.management.api.link.TeLinkAccessType;
+import org.onosproject.tetopology.management.api.link.UnderlayBackupPath;
+import org.onosproject.tetopology.management.api.link.UnderlayPrimaryPath;
+import org.onosproject.tetopology.management.api.link.UnnumberedLink;
+import org.onosproject.tetopology.management.api.link.UnreservedBandwidth;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
+import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
+import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
+import org.onosproject.tetopology.management.api.node.InterfaceSwitchingCapability;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNetworkTopologyId;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TeStatus;
+import org.onosproject.tetopology.management.api.node.TeTerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationCapability;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
+import org.onosproject.tetopology.management.api.TeTopologyStore;
+import org.onosproject.tetopology.management.api.TeTopologyStoreDelegate;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.DefaultNetworks;
+import org.onosproject.tetopology.management.api.InternalTeNetwork;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of the IETF network store.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedTeTopologyStore
+ extends AbstractStore<TeTopologyEvent, TeTopologyStoreDelegate>
+ implements TeTopologyStore {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ // Track networks by network key
+ private ConsistentMap<KeyId, InternalTeNetwork> networkIdNetworkConsistentMap;
+ private Map<KeyId, InternalTeNetwork> networkIdNetworkMap;
+
+ // Listener for network events
+ private final MapEventListener<KeyId, InternalTeNetwork> networkMapListener = new InternalNetworkMapListener();
+
+ private static final Serializer NETWORK_SERIALIZER = Serializer
+ .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
+ .register(KeyId.class)
+ .register(InternalTeNetwork.class)
+ .register(TeTopologyId.class)
+ .register(DefaultNetwork.class)
+ .register(DefaultNetworks.class)
+ .register(InternalTeNetwork.class)
+ .register(Network.class)
+ .register(Networks.class)
+ .register(TeTopologyType.class)
+ .register(TeIpv4.class)
+ .register(NetworkLinkKey.class)
+ .register(NetworkLink.class)
+ .register(PathElement.class)
+ .register(TeLink.class)
+ .register(UnderlayBackupPath.class)
+ .register(UnderlayPrimaryPath.class)
+ .register(UnnumberedLink.class)
+ .register(UnreservedBandwidth.class)
+ .register(InterfaceSwitchingCapability.class)
+ .register(NetworkNode.class)
+ .register(TeNode.class)
+ .register(TerminationPoint.class)
+ .register(TeTerminationPoint.class)
+ .register(TerminationCapability.class)
+ .register(TeStatus.class)
+ .register(TunnelTerminationPoint.class)
+ .register(DefaultNetworkLink.class)
+ .register(DefaultNetworkNode.class)
+ .register(DefaultTerminationPoint.class)
+ .register(TerminationPointKey.class)
+ .register(TeNetworkTopologyId.class)
+ .register(NetworkNodeKey.class)
+ .register(ConnectivityMatrix.class)
+ .register(TeTopologyId.class)
+ .register(TeLinkAccessType.class)
+ .register(BigInteger.class)
+ .register(String.class)
+ .register(Long.class)
+ .register(Boolean.class)
+ .register(BigDecimal.class)
+ .register(Short.class)
+ .register(IpAddress.class)
+ .register(Integer.class)
+ .register(ExternalDomain.class)
+ .register(ElementType.class)
+ .register(LinkProtectionType.class)
+ .register(Label.class)
+ .register(TeIpv6.class)
+ .register(AsNumber.class)
+ .build());
+
+ /**
+ * Distributed network store service activate method.
+ */
+ @Activate
+ public void activate() {
+ log.info("TE topology store is activated");
+ networkIdNetworkConsistentMap = storageService.<KeyId, InternalTeNetwork>consistentMapBuilder()
+ .withSerializer(NETWORK_SERIALIZER)
+ .withName("networkId-network")
+ .withRelaxedReadConsistency()
+ .build();
+ networkIdNetworkConsistentMap.addListener(networkMapListener);
+ networkIdNetworkMap = networkIdNetworkConsistentMap.asJavaMap();
+
+ log.info("Started");
+ }
+
+ /**
+ * Distributed network store service deactivate method.
+ */
+ @Deactivate
+ public void deactivate() {
+ networkIdNetworkConsistentMap.removeListener(networkMapListener);
+ log.info("Stopped");
+ }
+
+ @Override
+ public List<InternalTeNetwork> getNetworks(TeTopologyType type) {
+ List<InternalTeNetwork> networks = new ArrayList<>();
+
+ for (Map.Entry<KeyId, InternalTeNetwork> entry:networkIdNetworkMap.entrySet()) {
+ KeyId networkId = entry.getKey();
+ InternalTeNetwork network = entry.getValue();
+
+ if (network.getTeTopologyType() == type ||
+ type == TeTopologyType.ANY) {
+ networks.add(network);
+ }
+ }
+
+ return networks;
+ }
+
+ @Override
+ public InternalTeNetwork getNetwork(KeyId networkId) {
+ return networkIdNetworkMap.get(networkId);
+ }
+
+ @Override
+ public void updateNetwork(InternalTeNetwork network) {
+ //TODO - check the validity of the network before updating
+ log.info("network = {}", network);
+ networkIdNetworkMap.put(network.networkId(), network);
+ }
+
+ @Override
+ public void removeNetwork(KeyId networkId) {
+ networkIdNetworkMap.remove(networkId);
+ }
+
+ /**
+ * Listener class to map listener map events to the network events.
+ */
+ private class InternalNetworkMapListener implements MapEventListener<KeyId, InternalTeNetwork> {
+ @Override
+ public void event(MapEvent<KeyId, InternalTeNetwork> event) {
+ TeTopologyEvent.Type type = null;
+ TeTopologyEvent topologyEvent = null;
+ switch (event.type()) {
+ case INSERT:
+ type = TeTopologyEvent.Type.NETWORK_ADDED;
+ // Need to check if nodes/links are already in, otherwise errors
+ topologyEvent = new TeTopologyEvent(type, event.newValue().value());
+ break;
+ case UPDATE:
+ // Need to check what attributes change, and coordinate with other Node/Link events.
+ if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
+ type = TeTopologyEvent.Type.NETWORK_REMOVED;
+ topologyEvent = new TeTopologyEvent(type, event.oldValue().value());
+ } else {
+ type = TeTopologyEvent.Type.NETWORK_UPDATED;
+ topologyEvent = new TeTopologyEvent(type, event.newValue().value());
+ }
+ break;
+ case REMOVE:
+ type = TeTopologyEvent.Type.NETWORK_REMOVED;
+ topologyEvent = new TeTopologyEvent(type, event.oldValue().value());
+ break;
+ default:
+ log.error("Unsupported event type: {}", event.type());
+ }
+ log.info("Event type {}, Event {}", type, topologyEvent);
+ if (topologyEvent != null) {
+ notifyDelegate(topologyEvent);
+ }
+ }
+ }
+
+}
+
diff --git a/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyIdConfig.java b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyIdConfig.java
new file mode 100644
index 0000000..4cfe0d8
--- /dev/null
+++ b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyIdConfig.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 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.tetopology.management.impl;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.net.config.Config;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+
+/**
+ * Configuration for TE Topology Identifiers.
+ */
+public class TeTopologyIdConfig extends Config<ApplicationId> {
+ public static final String CONFIG_VALUE_ERROR = "Error parsing config value";
+ private static final String PROVIDER_ID = "provider-id";
+ private static final String CLIENT_ID = "client-id";
+ private static final String TOPOLOGY_ID = "topology-id";
+
+ /**
+ * Generates TE topology identifier.
+ *
+ * @return encoded TE topology identifier
+ * @throws ConfigException if the parameters are not correctly configured
+ * or conversion of the parameters fails
+ */
+ public TeTopologyId getTeTopologyId() throws ConfigException {
+ try {
+ long providerId = object.path(PROVIDER_ID).asLong();
+ long clientId = object.path(CLIENT_ID).asLong();
+ String topologyId = object.path(TOPOLOGY_ID).asText();
+
+ return new TeTopologyId(providerId, clientId, topologyId);
+
+ } catch (IllegalArgumentException e) {
+ throw new ConfigException(CONFIG_VALUE_ERROR, e);
+ }
+ }
+}
diff --git a/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
new file mode 100644
index 0000000..358237a
--- /dev/null
+++ b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
@@ -0,0 +1,497 @@
+/*
+ * Copyright 2016 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.tetopology.management.impl;
+
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collection;
+
+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.Ip4Address;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.device.DeviceProvider;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.link.LinkProvider;
+import org.onosproject.net.link.LinkProviderRegistry;
+import org.onosproject.net.link.LinkProviderService;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.provider.AbstractListenerProviderRegistry;
+import org.onosproject.net.provider.AbstractProviderService;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.tetopology.management.api.DefaultNetwork;
+import org.onosproject.tetopology.management.api.DefaultNetworks;
+import org.onosproject.tetopology.management.api.InternalTeNetwork;
+import org.onosproject.tetopology.management.api.KeyId;
+import org.onosproject.tetopology.management.api.Network;
+import org.onosproject.tetopology.management.api.Networks;
+import org.onosproject.tetopology.management.api.TeTopologyEvent;
+import org.onosproject.tetopology.management.api.TeTopologyId;
+import org.onosproject.tetopology.management.api.TeTopologyListener;
+import org.onosproject.tetopology.management.api.TeTopologyProvider;
+import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
+import org.onosproject.tetopology.management.api.TeTopologyProviderService;
+import org.onosproject.tetopology.management.api.TeTopologyService;
+import org.onosproject.tetopology.management.api.TeTopologyStore;
+import org.onosproject.tetopology.management.api.TeTopologyStoreDelegate;
+import org.onosproject.tetopology.management.api.TeTopologyType;
+import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLink;
+import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
+import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
+import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
+import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
+import org.onosproject.tetopology.management.api.node.NetworkNode;
+import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
+import org.onosproject.tetopology.management.api.node.TeNode;
+import org.onosproject.tetopology.management.api.node.TerminationPoint;
+import org.onosproject.tetopology.management.api.node.TerminationPointKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Implementation of the topology management service.
+ */
+@Component(immediate = true)
+@Service
+public class TeTopologyManager
+ extends AbstractListenerProviderRegistry<TeTopologyEvent, TeTopologyListener,
+ TeTopologyProvider, TeTopologyProviderService>
+ implements TeTopologyService, TeTopologyProviderRegistry, DeviceProvider, LinkProvider {
+ private static final String APP_NAME = "org.onosproject.tetopology";
+ private static final String IETF_TE_TOPOLOGY_MANAGER = "ietf-te-topology-manager";
+ private static final String PROVIDER = "org.onosproject.provider.ietfte.objects";
+ private static final long MY_PROVIDER_ID = 0x0a0a0a0aL;
+ private static final long DEFAUL_CLIENT_ID = 0x00L;
+ private static final String MY_NATIVE_TOPOLOGY_ID = "onos-sc-topo-1";
+ private static final TeTopologyId DEFAULT_TOPOLOGY_ID = new TeTopologyId(MY_PROVIDER_ID,
+ DEFAUL_CLIENT_ID,
+ MY_NATIVE_TOPOLOGY_ID);
+ //teTopologyId is configurable from Network Config
+ private TeTopologyId teTopologyId = DEFAULT_TOPOLOGY_ID;
+
+ private static final Ip4Address NEW_TE_NODE_ID_START = Ip4Address.valueOf("1.1.1.1");
+ private static final Ip4Address NEW_TE_NODE_ID_END = Ip4Address.valueOf("1.1.250.250");
+ private static final String MDSC_URI_PREFIX = "MDSC";
+ private static Ip4Address newTeNodeId = NEW_TE_NODE_ID_START;
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry cfgService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkService linkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceProviderRegistry deviceProviderRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkProviderRegistry linkProviderRegistry;
+
+ //Only network level data is stored in this subsystem.
+ //Link and Device details is stored in Link and Device subsystems.
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ public TeTopologyStore store;
+
+ //private TeTopologyStoreDelegate delegate = this::post;
+ private final TeTopologyStoreDelegate delegate = new InternalStoreDelegate();
+
+ private final ConfigFactory<ApplicationId, TeTopologyIdConfig> factory =
+ new ConfigFactory<ApplicationId, TeTopologyIdConfig>(APP_SUBJECT_FACTORY,
+ TeTopologyIdConfig.class,
+ "teTopologyId",
+ true) {
+ @Override
+ public TeTopologyIdConfig createConfig() {
+ return new TeTopologyIdConfig();
+ }
+ };
+ private final NetworkConfigListener cfgLister = new InternalConfigListener();
+ private ApplicationId appId;
+
+ private DeviceProviderService deviceProviderService;
+ private LinkProviderService linkProviderService;
+
+ /**
+ * Activation helper function.
+ */
+ public void activateBasics() {
+ store.setDelegate(delegate);
+ eventDispatcher.addSink(TeTopologyEvent.class, listenerRegistry);
+ }
+
+ /**
+ * Deactivation helper function.
+ */
+ public void deactivateBasics() {
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(TeTopologyEvent.class);
+ }
+
+ @Activate
+ public void activate() {
+ activateBasics();
+ appId = coreService.registerApplication(APP_NAME);
+ cfgService.registerConfigFactory(factory);
+ cfgService.addListener(cfgLister);
+
+ deviceProviderService = deviceProviderRegistry.register(this);
+ linkProviderService = linkProviderRegistry.register(this);
+
+ //TODO: Needs to add the event listener into LINK and Device subsystem
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ deactivateBasics();
+
+ cfgService.removeListener(cfgLister);
+ cfgService.unregisterConfigFactory(factory);
+
+ deviceProviderRegistry.unregister(this);
+ linkProviderRegistry.unregister(this);
+
+ //TODO: Needs to remove the event listener from LINK and Device subsystem
+
+ log.info("Stopped");
+ }
+
+ @Override
+ public Networks getNetworks() {
+ // return a list of the native networks
+ List<InternalTeNetwork> teNetworks = store.getNetworks(TeTopologyType.NATIVE);
+
+ List<Network> defaultNetworks = new ArrayList<>();
+ for (InternalTeNetwork teNetwork : teNetworks) {
+ defaultNetworks.add(teNetwork);
+ }
+
+ return (new DefaultNetworks(defaultNetworks));
+ }
+
+ @Override
+ public Network getNetwork(KeyId networkId) {
+ return new DefaultNetwork(store.getNetwork(networkId));
+ }
+
+ @Override
+ public void updateNetwork(Network network) {
+ store.updateNetwork(new InternalTeNetwork(TeTopologyType.CONFIGURED, new DefaultNetwork(network)));
+ //TODO: Need to update nodes and links to Device/Link subsystems.
+ }
+
+ @Override
+ public void removeNetwork(KeyId networkId) {
+ store.removeNetwork(networkId);
+ }
+
+ @Override
+ protected TeTopologyProviderService createProviderService(TeTopologyProvider provider) {
+ return new InternalTopologyProviderService(provider);
+ }
+
+ private class InternalTopologyProviderService
+ extends AbstractProviderService<TeTopologyProvider>
+ implements TeTopologyProviderService {
+
+ protected InternalTopologyProviderService(TeTopologyProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public void networkUpdated(Network network) {
+ // Store received network data into the local TE topology data store
+ InternalTeNetwork teNetwork = new InternalTeNetwork(TeTopologyType.SUBORDINATE, network);
+ store.updateNetwork(teNetwork);
+
+ // let's do it here for now
+ mergeNetworks();
+
+ //TODO: Store node and link in Device/Link subsystem
+ //deviceProviderService.deviceConnected(arg0, arg1);
+ //linkProviderService.linkDetected(arg0);
+ }
+
+ @Override
+ public void networkRemoved(KeyId networkId) {
+ store.removeNetwork(networkId);
+ }
+
+ @Override
+ public void linkUpdated(NetworkLinkKey linkKey, NetworkLink link) {
+ // Need to check if this is a new link
+
+ //deviceProviderService.deviceConnected(arg0, arg1);
+ }
+
+ @Override
+ public void linkRemoved(NetworkLinkKey linkKey) {
+ // No action is required (TODO: Auto-generated method stub)
+ }
+
+ @Override
+ public void nodeUpdated(NetworkNodeKey nodeKey, NetworkNode node) {
+ // Need to check if this is a new node
+
+ // No action is required (TODO: Auto-generated method stub)
+ }
+
+ @Override
+ public void nodeRemoved(NetworkNodeKey nodeKey) {
+ // No action is required (TODO: Auto-generated method stub)
+ }
+
+ @Override
+ public void terminationPointUpdated(TerminationPointKey terminationPointKey,
+ TerminationPoint terminationPoint) {
+ // No action is required (TODO: Auto-generated method stub)
+ }
+
+ @Override
+ public void terminationPointRemoved(TerminationPointKey terminationPointKey) {
+ // No action is required (TODO: Auto-generated method stub)
+ }
+
+ }
+
+ private class InternalStoreDelegate implements TeTopologyStoreDelegate {
+ @Override
+ public void notify(TeTopologyEvent event) {
+ if (event != null) {
+ //post(event);
+ processEvent(event);
+ }
+ }
+ }
+
+ private void processEvent(TeTopologyEvent event) {
+ log.info("ProcessEvent {}", event.type().toString());
+
+ //TODO - partial merge when network is updated
+ if (event.type() == TeTopologyEvent.Type.NETWORK_ADDED) {
+ // move network merging to networkUpdated()
+ //mergeNetworks();
+ }
+
+ //TODO: Merge node and links from Device/Links subsytems if required.
+
+ post(event);
+ }
+
+ private void mergeNetworks() {
+ /*
+ * Merge all subordinate TE topologies, create a simple merged native topology
+ * and store it in the topology store.
+ */
+ /* TODO - generate new id based on its provider id + network id */
+ KeyId newNetworkId = KeyId.keyId(Long.toString(teTopologyId.providerId()) + "-" + teTopologyId.topologyId());
+ store.removeNetwork(newNetworkId);
+ /* create list of links, nodes and termination points */
+ List<NetworkLink> allLinks = new ArrayList<>();
+ List<NetworkNode> allNodes = new ArrayList<>();
+ List<KeyId> allSupportingNetworkIds = new ArrayList<>();
+
+ /* translate keys for links/nodes/tps */
+ List<InternalTeNetwork> subordNetworks = store.getNetworks(TeTopologyType.SUBORDINATE);
+ for (InternalTeNetwork network : subordNetworks) {
+ allSupportingNetworkIds.add(network.networkId());
+
+ /* create and add new nodes */
+ List<NetworkNode> nodes = network.getNodes();
+ for (NetworkNode node : nodes) {
+
+ KeyId newNodeId = KeyId.keyId(MDSC_URI_PREFIX + node.nodeId());
+ TeNode newTeNode = null;
+ TeNode origTeNode = node.getTe();
+ if (origTeNode != null) {
+ newTeNode = new TeNode(origTeNode.teNodeId());
+ newTeNode.setName(origTeNode.name());
+ newTeNode.setAdminStatus(origTeNode.adminStatus());
+ newTeNode.setOpStatus(origTeNode.opStatus());
+ newTeNode.setAbstract(origTeNode.isAbstract());
+ List<ConnectivityMatrix> newConnMatrices = new ArrayList<>();
+
+ for (ConnectivityMatrix conn : origTeNode.connectivityMatrices()) {
+ KeyId tpId = conn.from().tpId();
+ KeyId newFromTpId = KeyId.keyId(MDSC_URI_PREFIX + tpId);
+ TerminationPointKey newFrom = new TerminationPointKey(newNetworkId, newNodeId, newFromTpId);
+
+ tpId = conn.to().tpId();
+ KeyId newToTpId = KeyId.keyId(MDSC_URI_PREFIX + tpId);
+ TerminationPointKey newTo = new TerminationPointKey(newNetworkId, newNodeId, newToTpId);
+ ConnectivityMatrix newConnMatrix =
+ new ConnectivityMatrix(conn.id(), newFrom, newTo, conn.isAllowed());
+ newConnMatrices.add(newConnMatrix);
+ }
+ newTeNode.setConnectivityMatrices(newConnMatrices);
+ newTeNode.setUnderlayTopology(origTeNode.underlayTopology());
+ newTeNode.setTunnelTerminationPoints(origTeNode.tunnelTerminationPoints());
+ }
+ List<NetworkNodeKey> supportingNodes = Lists.newArrayList();
+ supportingNodes.add(new NetworkNodeKey(network.networkId(), node.nodeId()));
+ DefaultNetworkNode newNode =
+ new DefaultNetworkNode(newNodeId, supportingNodes, newTeNode);
+ List<TerminationPoint> newTps = Lists.newArrayList();
+
+ List<TerminationPoint> origTps = node.getTerminationPoints();
+ if (nonEmpty(origTps)) {
+ for (TerminationPoint tp : origTps) {
+ DefaultTerminationPoint newTp =
+ new DefaultTerminationPoint(KeyId.keyId(MDSC_URI_PREFIX + tp.id()));
+ List<TerminationPointKey> supportTps = Lists.newArrayList();
+ supportTps.add(new TerminationPointKey(network.networkId(), node.nodeId(), tp.id()));
+ newTp.setSupportingTpIds(supportTps);
+ newTps.add(newTp);
+ }
+ }
+ newNode.setTerminationPoints(newTps);
+ allNodes.add(newNode);
+ }
+
+ /* create and add new links */
+ List<NetworkLink> links = network.getLinks();
+ if (nonEmpty(links)) {
+ for (NetworkLink link : links) {
+ KeyId newLinkId = KeyId.keyId(MDSC_URI_PREFIX + link.linkId());
+ KeyId k = link.getSource().nodeId();
+ KeyId newSourceNodeId =
+ KeyId.keyId(MDSC_URI_PREFIX + k);
+ k = link.getSource().tpId();
+ KeyId newSourceNodeTpId =
+ KeyId.keyId(MDSC_URI_PREFIX + k);
+ k = link.getDestination().nodeId();
+ KeyId newDestNodeId =
+ KeyId.keyId(MDSC_URI_PREFIX + k);
+ k = link.getDestination().tpId();
+ KeyId newDestNodeTpId =
+ KeyId.keyId(MDSC_URI_PREFIX + k);
+ TerminationPointKey newSourceNodeTp =
+ new TerminationPointKey(newNetworkId, newSourceNodeId, newSourceNodeTpId);
+ TerminationPointKey newDestNodeTp =
+ new TerminationPointKey(newNetworkId, newDestNodeId, newDestNodeTpId);
+
+ DefaultNetworkLink newLink = new DefaultNetworkLink(newLinkId);
+ newLink.setSource(newSourceNodeTp);
+ newLink.setDestination(newDestNodeTp);
+ List<NetworkLinkKey> supportLinks = Lists.newArrayList();
+ supportLinks.add(new NetworkLinkKey(network.networkId(), link.linkId()));
+ newLink.setSupportingLinkIds(supportLinks);
+ newLink.setTe(link.getTe());
+
+ allLinks.add(newLink);
+ }
+ }
+ }
+
+ /* save generated native TE network into the store */
+ if (allNodes.size() > 0) {
+ //TeTopologyId newTopoId = new TeTopologyId(MY_PROVIDER_ID, 0L, NATIVE_TOPOLOGY_ID);
+ DefaultNetwork nativeDefaultNetwork =
+ new DefaultNetwork(newNetworkId, allSupportingNetworkIds, allNodes, allLinks, teTopologyId, true);
+ InternalTeNetwork newTeNetwork = new InternalTeNetwork(TeTopologyType.NATIVE, nativeDefaultNetwork);
+ store.updateNetwork(newTeNetwork);
+ }
+ }
+
+ @Override
+ public ProviderId id() {
+ return new ProviderId(IETF_TE_TOPOLOGY_MANAGER, PROVIDER);
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ try {
+ teTopologyId = cfgService.getConfig(appId, TeTopologyIdConfig.class).getTeTopologyId();
+ } catch (ConfigException e) {
+ log.error("Configuration error {}", e);
+ }
+ log.info("new teTopologyId is {}", teTopologyId);
+ }
+
+ @Override
+ public boolean isRelevant(NetworkConfigEvent event) {
+ return event.configClass().equals(TeTopologyIdConfig.class) &&
+ (event.type() == CONFIG_ADDED ||
+ event.type() == CONFIG_UPDATED);
+ }
+ }
+
+ @Override
+ public void changePortState(DeviceId arg0, PortNumber arg1, boolean arg2) {
+ // TODO: This will be implemented if required.
+ }
+
+ @Override
+ public boolean isReachable(DeviceId arg0) {
+ // TODO: This will be implemented if required.
+ return false;
+ }
+
+ @Override
+ public void roleChanged(DeviceId arg0, MastershipRole arg1) {
+ // TODO: This will be implemented if required.
+ }
+
+ @Override
+ public void triggerProbe(DeviceId arg0) {
+ // TODO: This will be implemented if required.
+ }
+
+ private Ip4Address assignTeNodeId() {
+ int value = newTeNodeId.toInt();
+
+ if (value >= NEW_TE_NODE_ID_END.toInt()) {
+ value = NEW_TE_NODE_ID_START.toInt();
+ }
+ return Ip4Address.valueOf(value);
+ }
+
+ private static boolean nonEmpty(Collection<?> c) {
+ return c != null && !c.isEmpty();
+ }
+}
diff --git a/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/package-info.java b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/package-info.java
new file mode 100644
index 0000000..b2c69be
--- /dev/null
+++ b/apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/package-info.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2016 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.
+ */
+
+/**
+ * TE Topology Management implementation.
+ */
+package org.onosproject.tetopology.management.impl;