Committed by
Gerrit Code Review
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
Showing
5 changed files
with
828 additions
and
0 deletions
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.tetopology.management.impl; | ||
| 17 | + | ||
| 18 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 19 | + | ||
| 20 | +import java.util.List; | ||
| 21 | +import java.lang.annotation.ElementType; | ||
| 22 | +import java.math.BigDecimal; | ||
| 23 | +import java.math.BigInteger; | ||
| 24 | +import java.util.ArrayList; | ||
| 25 | +import java.util.Map; | ||
| 26 | + | ||
| 27 | +import org.apache.felix.scr.annotations.Activate; | ||
| 28 | +import org.apache.felix.scr.annotations.Component; | ||
| 29 | +import org.apache.felix.scr.annotations.Deactivate; | ||
| 30 | +import org.apache.felix.scr.annotations.Reference; | ||
| 31 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
| 32 | +import org.apache.felix.scr.annotations.Service; | ||
| 33 | +import org.onlab.packet.IpAddress; | ||
| 34 | +import org.onlab.util.KryoNamespace; | ||
| 35 | +import org.onosproject.store.AbstractStore; | ||
| 36 | +import org.onosproject.store.serializers.KryoNamespaces; | ||
| 37 | +import org.onosproject.store.service.ConsistentMap; | ||
| 38 | +import org.onosproject.store.service.MapEvent; | ||
| 39 | +import org.onosproject.store.service.MapEventListener; | ||
| 40 | +import org.onosproject.store.service.Serializer; | ||
| 41 | +import org.onosproject.store.service.StorageService; | ||
| 42 | +import org.onosproject.tetopology.management.api.KeyId; | ||
| 43 | +import org.onosproject.tetopology.management.api.Network; | ||
| 44 | +import org.onosproject.tetopology.management.api.Networks; | ||
| 45 | +import org.onosproject.tetopology.management.api.TeTopologyEvent; | ||
| 46 | +import org.onosproject.tetopology.management.api.TeTopologyId; | ||
| 47 | +import org.onosproject.tetopology.management.api.TeTopologyType; | ||
| 48 | +import org.onosproject.tetopology.management.api.link.AsNumber; | ||
| 49 | +import org.onosproject.tetopology.management.api.link.DefaultNetworkLink; | ||
| 50 | +import org.onosproject.tetopology.management.api.link.ExternalDomain; | ||
| 51 | +import org.onosproject.tetopology.management.api.link.TeIpv4; | ||
| 52 | +import org.onosproject.tetopology.management.api.link.TeIpv6; | ||
| 53 | +import org.onosproject.tetopology.management.api.link.Label; | ||
| 54 | +import org.onosproject.tetopology.management.api.link.LinkProtectionType; | ||
| 55 | +import org.onosproject.tetopology.management.api.link.NetworkLink; | ||
| 56 | +import org.onosproject.tetopology.management.api.link.NetworkLinkKey; | ||
| 57 | +import org.onosproject.tetopology.management.api.link.PathElement; | ||
| 58 | +import org.onosproject.tetopology.management.api.link.TeLink; | ||
| 59 | +import org.onosproject.tetopology.management.api.link.TeLinkAccessType; | ||
| 60 | +import org.onosproject.tetopology.management.api.link.UnderlayBackupPath; | ||
| 61 | +import org.onosproject.tetopology.management.api.link.UnderlayPrimaryPath; | ||
| 62 | +import org.onosproject.tetopology.management.api.link.UnnumberedLink; | ||
| 63 | +import org.onosproject.tetopology.management.api.link.UnreservedBandwidth; | ||
| 64 | +import org.onosproject.tetopology.management.api.node.ConnectivityMatrix; | ||
| 65 | +import org.onosproject.tetopology.management.api.node.DefaultNetworkNode; | ||
| 66 | +import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint; | ||
| 67 | +import org.onosproject.tetopology.management.api.node.InterfaceSwitchingCapability; | ||
| 68 | +import org.onosproject.tetopology.management.api.node.NetworkNode; | ||
| 69 | +import org.onosproject.tetopology.management.api.node.NetworkNodeKey; | ||
| 70 | +import org.onosproject.tetopology.management.api.node.TeNetworkTopologyId; | ||
| 71 | +import org.onosproject.tetopology.management.api.node.TeNode; | ||
| 72 | +import org.onosproject.tetopology.management.api.node.TeStatus; | ||
| 73 | +import org.onosproject.tetopology.management.api.node.TeTerminationPoint; | ||
| 74 | +import org.onosproject.tetopology.management.api.node.TerminationCapability; | ||
| 75 | +import org.onosproject.tetopology.management.api.node.TerminationPoint; | ||
| 76 | +import org.onosproject.tetopology.management.api.node.TerminationPointKey; | ||
| 77 | +import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint; | ||
| 78 | +import org.onosproject.tetopology.management.api.TeTopologyStore; | ||
| 79 | +import org.onosproject.tetopology.management.api.TeTopologyStoreDelegate; | ||
| 80 | +import org.onosproject.tetopology.management.api.DefaultNetwork; | ||
| 81 | +import org.onosproject.tetopology.management.api.DefaultNetworks; | ||
| 82 | +import org.onosproject.tetopology.management.api.InternalTeNetwork; | ||
| 83 | +import org.slf4j.Logger; | ||
| 84 | + | ||
| 85 | +/** | ||
| 86 | + * Implementation of the IETF network store. | ||
| 87 | + */ | ||
| 88 | +@Component(immediate = true) | ||
| 89 | +@Service | ||
| 90 | +public class DistributedTeTopologyStore | ||
| 91 | + extends AbstractStore<TeTopologyEvent, TeTopologyStoreDelegate> | ||
| 92 | + implements TeTopologyStore { | ||
| 93 | + | ||
| 94 | + private final Logger log = getLogger(getClass()); | ||
| 95 | + | ||
| 96 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 97 | + protected StorageService storageService; | ||
| 98 | + | ||
| 99 | + // Track networks by network key | ||
| 100 | + private ConsistentMap<KeyId, InternalTeNetwork> networkIdNetworkConsistentMap; | ||
| 101 | + private Map<KeyId, InternalTeNetwork> networkIdNetworkMap; | ||
| 102 | + | ||
| 103 | + // Listener for network events | ||
| 104 | + private final MapEventListener<KeyId, InternalTeNetwork> networkMapListener = new InternalNetworkMapListener(); | ||
| 105 | + | ||
| 106 | + private static final Serializer NETWORK_SERIALIZER = Serializer | ||
| 107 | + .using(new KryoNamespace.Builder().register(KryoNamespaces.API) | ||
| 108 | + .register(KeyId.class) | ||
| 109 | + .register(InternalTeNetwork.class) | ||
| 110 | + .register(TeTopologyId.class) | ||
| 111 | + .register(DefaultNetwork.class) | ||
| 112 | + .register(DefaultNetworks.class) | ||
| 113 | + .register(InternalTeNetwork.class) | ||
| 114 | + .register(Network.class) | ||
| 115 | + .register(Networks.class) | ||
| 116 | + .register(TeTopologyType.class) | ||
| 117 | + .register(TeIpv4.class) | ||
| 118 | + .register(NetworkLinkKey.class) | ||
| 119 | + .register(NetworkLink.class) | ||
| 120 | + .register(PathElement.class) | ||
| 121 | + .register(TeLink.class) | ||
| 122 | + .register(UnderlayBackupPath.class) | ||
| 123 | + .register(UnderlayPrimaryPath.class) | ||
| 124 | + .register(UnnumberedLink.class) | ||
| 125 | + .register(UnreservedBandwidth.class) | ||
| 126 | + .register(InterfaceSwitchingCapability.class) | ||
| 127 | + .register(NetworkNode.class) | ||
| 128 | + .register(TeNode.class) | ||
| 129 | + .register(TerminationPoint.class) | ||
| 130 | + .register(TeTerminationPoint.class) | ||
| 131 | + .register(TerminationCapability.class) | ||
| 132 | + .register(TeStatus.class) | ||
| 133 | + .register(TunnelTerminationPoint.class) | ||
| 134 | + .register(DefaultNetworkLink.class) | ||
| 135 | + .register(DefaultNetworkNode.class) | ||
| 136 | + .register(DefaultTerminationPoint.class) | ||
| 137 | + .register(TerminationPointKey.class) | ||
| 138 | + .register(TeNetworkTopologyId.class) | ||
| 139 | + .register(NetworkNodeKey.class) | ||
| 140 | + .register(ConnectivityMatrix.class) | ||
| 141 | + .register(TeTopologyId.class) | ||
| 142 | + .register(TeLinkAccessType.class) | ||
| 143 | + .register(BigInteger.class) | ||
| 144 | + .register(String.class) | ||
| 145 | + .register(Long.class) | ||
| 146 | + .register(Boolean.class) | ||
| 147 | + .register(BigDecimal.class) | ||
| 148 | + .register(Short.class) | ||
| 149 | + .register(IpAddress.class) | ||
| 150 | + .register(Integer.class) | ||
| 151 | + .register(ExternalDomain.class) | ||
| 152 | + .register(ElementType.class) | ||
| 153 | + .register(LinkProtectionType.class) | ||
| 154 | + .register(Label.class) | ||
| 155 | + .register(TeIpv6.class) | ||
| 156 | + .register(AsNumber.class) | ||
| 157 | + .build()); | ||
| 158 | + | ||
| 159 | + /** | ||
| 160 | + * Distributed network store service activate method. | ||
| 161 | + */ | ||
| 162 | + @Activate | ||
| 163 | + public void activate() { | ||
| 164 | + log.info("TE topology store is activated"); | ||
| 165 | + networkIdNetworkConsistentMap = storageService.<KeyId, InternalTeNetwork>consistentMapBuilder() | ||
| 166 | + .withSerializer(NETWORK_SERIALIZER) | ||
| 167 | + .withName("networkId-network") | ||
| 168 | + .withRelaxedReadConsistency() | ||
| 169 | + .build(); | ||
| 170 | + networkIdNetworkConsistentMap.addListener(networkMapListener); | ||
| 171 | + networkIdNetworkMap = networkIdNetworkConsistentMap.asJavaMap(); | ||
| 172 | + | ||
| 173 | + log.info("Started"); | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + /** | ||
| 177 | + * Distributed network store service deactivate method. | ||
| 178 | + */ | ||
| 179 | + @Deactivate | ||
| 180 | + public void deactivate() { | ||
| 181 | + networkIdNetworkConsistentMap.removeListener(networkMapListener); | ||
| 182 | + log.info("Stopped"); | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + @Override | ||
| 186 | + public List<InternalTeNetwork> getNetworks(TeTopologyType type) { | ||
| 187 | + List<InternalTeNetwork> networks = new ArrayList<>(); | ||
| 188 | + | ||
| 189 | + for (Map.Entry<KeyId, InternalTeNetwork> entry:networkIdNetworkMap.entrySet()) { | ||
| 190 | + KeyId networkId = entry.getKey(); | ||
| 191 | + InternalTeNetwork network = entry.getValue(); | ||
| 192 | + | ||
| 193 | + if (network.getTeTopologyType() == type || | ||
| 194 | + type == TeTopologyType.ANY) { | ||
| 195 | + networks.add(network); | ||
| 196 | + } | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + return networks; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + @Override | ||
| 203 | + public InternalTeNetwork getNetwork(KeyId networkId) { | ||
| 204 | + return networkIdNetworkMap.get(networkId); | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | + @Override | ||
| 208 | + public void updateNetwork(InternalTeNetwork network) { | ||
| 209 | + //TODO - check the validity of the network before updating | ||
| 210 | + log.info("network = {}", network); | ||
| 211 | + networkIdNetworkMap.put(network.networkId(), network); | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + @Override | ||
| 215 | + public void removeNetwork(KeyId networkId) { | ||
| 216 | + networkIdNetworkMap.remove(networkId); | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + /** | ||
| 220 | + * Listener class to map listener map events to the network events. | ||
| 221 | + */ | ||
| 222 | + private class InternalNetworkMapListener implements MapEventListener<KeyId, InternalTeNetwork> { | ||
| 223 | + @Override | ||
| 224 | + public void event(MapEvent<KeyId, InternalTeNetwork> event) { | ||
| 225 | + TeTopologyEvent.Type type = null; | ||
| 226 | + TeTopologyEvent topologyEvent = null; | ||
| 227 | + switch (event.type()) { | ||
| 228 | + case INSERT: | ||
| 229 | + type = TeTopologyEvent.Type.NETWORK_ADDED; | ||
| 230 | + // Need to check if nodes/links are already in, otherwise errors | ||
| 231 | + topologyEvent = new TeTopologyEvent(type, event.newValue().value()); | ||
| 232 | + break; | ||
| 233 | + case UPDATE: | ||
| 234 | + // Need to check what attributes change, and coordinate with other Node/Link events. | ||
| 235 | + if ((event.oldValue().value() != null) && (event.newValue().value() == null)) { | ||
| 236 | + type = TeTopologyEvent.Type.NETWORK_REMOVED; | ||
| 237 | + topologyEvent = new TeTopologyEvent(type, event.oldValue().value()); | ||
| 238 | + } else { | ||
| 239 | + type = TeTopologyEvent.Type.NETWORK_UPDATED; | ||
| 240 | + topologyEvent = new TeTopologyEvent(type, event.newValue().value()); | ||
| 241 | + } | ||
| 242 | + break; | ||
| 243 | + case REMOVE: | ||
| 244 | + type = TeTopologyEvent.Type.NETWORK_REMOVED; | ||
| 245 | + topologyEvent = new TeTopologyEvent(type, event.oldValue().value()); | ||
| 246 | + break; | ||
| 247 | + default: | ||
| 248 | + log.error("Unsupported event type: {}", event.type()); | ||
| 249 | + } | ||
| 250 | + log.info("Event type {}, Event {}", type, topologyEvent); | ||
| 251 | + if (topologyEvent != null) { | ||
| 252 | + notifyDelegate(topologyEvent); | ||
| 253 | + } | ||
| 254 | + } | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | +} | ||
| 258 | + |
apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyIdConfig.java
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.tetopology.management.impl; | ||
| 17 | + | ||
| 18 | +import org.onosproject.core.ApplicationId; | ||
| 19 | +import org.onosproject.incubator.net.config.basics.ConfigException; | ||
| 20 | +import org.onosproject.net.config.Config; | ||
| 21 | +import org.onosproject.tetopology.management.api.TeTopologyId; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Configuration for TE Topology Identifiers. | ||
| 25 | + */ | ||
| 26 | +public class TeTopologyIdConfig extends Config<ApplicationId> { | ||
| 27 | + public static final String CONFIG_VALUE_ERROR = "Error parsing config value"; | ||
| 28 | + private static final String PROVIDER_ID = "provider-id"; | ||
| 29 | + private static final String CLIENT_ID = "client-id"; | ||
| 30 | + private static final String TOPOLOGY_ID = "topology-id"; | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * Generates TE topology identifier. | ||
| 34 | + * | ||
| 35 | + * @return encoded TE topology identifier | ||
| 36 | + * @throws ConfigException if the parameters are not correctly configured | ||
| 37 | + * or conversion of the parameters fails | ||
| 38 | + */ | ||
| 39 | + public TeTopologyId getTeTopologyId() throws ConfigException { | ||
| 40 | + try { | ||
| 41 | + long providerId = object.path(PROVIDER_ID).asLong(); | ||
| 42 | + long clientId = object.path(CLIENT_ID).asLong(); | ||
| 43 | + String topologyId = object.path(TOPOLOGY_ID).asText(); | ||
| 44 | + | ||
| 45 | + return new TeTopologyId(providerId, clientId, topologyId); | ||
| 46 | + | ||
| 47 | + } catch (IllegalArgumentException e) { | ||
| 48 | + throw new ConfigException(CONFIG_VALUE_ERROR, e); | ||
| 49 | + } | ||
| 50 | + } | ||
| 51 | +} |
apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.tetopology.management.impl; | ||
| 17 | + | ||
| 18 | +import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED; | ||
| 19 | +import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED; | ||
| 20 | +import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; | ||
| 21 | + | ||
| 22 | +import java.util.ArrayList; | ||
| 23 | +import java.util.List; | ||
| 24 | +import java.util.Collection; | ||
| 25 | + | ||
| 26 | +import org.apache.felix.scr.annotations.Activate; | ||
| 27 | +import org.apache.felix.scr.annotations.Component; | ||
| 28 | +import org.apache.felix.scr.annotations.Deactivate; | ||
| 29 | +import org.apache.felix.scr.annotations.Reference; | ||
| 30 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
| 31 | +import org.apache.felix.scr.annotations.Service; | ||
| 32 | +import org.onlab.packet.Ip4Address; | ||
| 33 | +import org.onosproject.core.ApplicationId; | ||
| 34 | +import org.onosproject.core.CoreService; | ||
| 35 | +import org.onosproject.incubator.net.config.basics.ConfigException; | ||
| 36 | +import org.onosproject.net.DeviceId; | ||
| 37 | +import org.onosproject.net.MastershipRole; | ||
| 38 | +import org.onosproject.net.PortNumber; | ||
| 39 | +import org.onosproject.net.config.ConfigFactory; | ||
| 40 | +import org.onosproject.net.config.NetworkConfigEvent; | ||
| 41 | +import org.onosproject.net.config.NetworkConfigListener; | ||
| 42 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
| 43 | +import org.onosproject.net.device.DeviceProvider; | ||
| 44 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
| 45 | +import org.onosproject.net.device.DeviceProviderService; | ||
| 46 | +import org.onosproject.net.device.DeviceService; | ||
| 47 | +import org.onosproject.net.link.LinkProvider; | ||
| 48 | +import org.onosproject.net.link.LinkProviderRegistry; | ||
| 49 | +import org.onosproject.net.link.LinkProviderService; | ||
| 50 | +import org.onosproject.net.link.LinkService; | ||
| 51 | +import org.onosproject.net.provider.AbstractListenerProviderRegistry; | ||
| 52 | +import org.onosproject.net.provider.AbstractProviderService; | ||
| 53 | +import org.onosproject.net.provider.ProviderId; | ||
| 54 | +import org.onosproject.tetopology.management.api.DefaultNetwork; | ||
| 55 | +import org.onosproject.tetopology.management.api.DefaultNetworks; | ||
| 56 | +import org.onosproject.tetopology.management.api.InternalTeNetwork; | ||
| 57 | +import org.onosproject.tetopology.management.api.KeyId; | ||
| 58 | +import org.onosproject.tetopology.management.api.Network; | ||
| 59 | +import org.onosproject.tetopology.management.api.Networks; | ||
| 60 | +import org.onosproject.tetopology.management.api.TeTopologyEvent; | ||
| 61 | +import org.onosproject.tetopology.management.api.TeTopologyId; | ||
| 62 | +import org.onosproject.tetopology.management.api.TeTopologyListener; | ||
| 63 | +import org.onosproject.tetopology.management.api.TeTopologyProvider; | ||
| 64 | +import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry; | ||
| 65 | +import org.onosproject.tetopology.management.api.TeTopologyProviderService; | ||
| 66 | +import org.onosproject.tetopology.management.api.TeTopologyService; | ||
| 67 | +import org.onosproject.tetopology.management.api.TeTopologyStore; | ||
| 68 | +import org.onosproject.tetopology.management.api.TeTopologyStoreDelegate; | ||
| 69 | +import org.onosproject.tetopology.management.api.TeTopologyType; | ||
| 70 | +import org.onosproject.tetopology.management.api.link.DefaultNetworkLink; | ||
| 71 | +import org.onosproject.tetopology.management.api.link.NetworkLink; | ||
| 72 | +import org.onosproject.tetopology.management.api.link.NetworkLinkKey; | ||
| 73 | +import org.onosproject.tetopology.management.api.node.ConnectivityMatrix; | ||
| 74 | +import org.onosproject.tetopology.management.api.node.DefaultNetworkNode; | ||
| 75 | +import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint; | ||
| 76 | +import org.onosproject.tetopology.management.api.node.NetworkNode; | ||
| 77 | +import org.onosproject.tetopology.management.api.node.NetworkNodeKey; | ||
| 78 | +import org.onosproject.tetopology.management.api.node.TeNode; | ||
| 79 | +import org.onosproject.tetopology.management.api.node.TerminationPoint; | ||
| 80 | +import org.onosproject.tetopology.management.api.node.TerminationPointKey; | ||
| 81 | +import org.slf4j.Logger; | ||
| 82 | +import org.slf4j.LoggerFactory; | ||
| 83 | + | ||
| 84 | +import com.google.common.collect.Lists; | ||
| 85 | + | ||
| 86 | +/** | ||
| 87 | + * Implementation of the topology management service. | ||
| 88 | + */ | ||
| 89 | +@Component(immediate = true) | ||
| 90 | +@Service | ||
| 91 | +public class TeTopologyManager | ||
| 92 | + extends AbstractListenerProviderRegistry<TeTopologyEvent, TeTopologyListener, | ||
| 93 | + TeTopologyProvider, TeTopologyProviderService> | ||
| 94 | + implements TeTopologyService, TeTopologyProviderRegistry, DeviceProvider, LinkProvider { | ||
| 95 | + private static final String APP_NAME = "org.onosproject.tetopology"; | ||
| 96 | + private static final String IETF_TE_TOPOLOGY_MANAGER = "ietf-te-topology-manager"; | ||
| 97 | + private static final String PROVIDER = "org.onosproject.provider.ietfte.objects"; | ||
| 98 | + private static final long MY_PROVIDER_ID = 0x0a0a0a0aL; | ||
| 99 | + private static final long DEFAUL_CLIENT_ID = 0x00L; | ||
| 100 | + private static final String MY_NATIVE_TOPOLOGY_ID = "onos-sc-topo-1"; | ||
| 101 | + private static final TeTopologyId DEFAULT_TOPOLOGY_ID = new TeTopologyId(MY_PROVIDER_ID, | ||
| 102 | + DEFAUL_CLIENT_ID, | ||
| 103 | + MY_NATIVE_TOPOLOGY_ID); | ||
| 104 | + //teTopologyId is configurable from Network Config | ||
| 105 | + private TeTopologyId teTopologyId = DEFAULT_TOPOLOGY_ID; | ||
| 106 | + | ||
| 107 | + private static final Ip4Address NEW_TE_NODE_ID_START = Ip4Address.valueOf("1.1.1.1"); | ||
| 108 | + private static final Ip4Address NEW_TE_NODE_ID_END = Ip4Address.valueOf("1.1.250.250"); | ||
| 109 | + private static final String MDSC_URI_PREFIX = "MDSC"; | ||
| 110 | + private static Ip4Address newTeNodeId = NEW_TE_NODE_ID_START; | ||
| 111 | + | ||
| 112 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 113 | + | ||
| 114 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 115 | + protected CoreService coreService; | ||
| 116 | + | ||
| 117 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 118 | + protected NetworkConfigRegistry cfgService; | ||
| 119 | + | ||
| 120 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 121 | + protected DeviceService deviceService; | ||
| 122 | + | ||
| 123 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 124 | + protected LinkService linkService; | ||
| 125 | + | ||
| 126 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 127 | + protected DeviceProviderRegistry deviceProviderRegistry; | ||
| 128 | + | ||
| 129 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 130 | + protected LinkProviderRegistry linkProviderRegistry; | ||
| 131 | + | ||
| 132 | + //Only network level data is stored in this subsystem. | ||
| 133 | + //Link and Device details is stored in Link and Device subsystems. | ||
| 134 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 135 | + public TeTopologyStore store; | ||
| 136 | + | ||
| 137 | + //private TeTopologyStoreDelegate delegate = this::post; | ||
| 138 | + private final TeTopologyStoreDelegate delegate = new InternalStoreDelegate(); | ||
| 139 | + | ||
| 140 | + private final ConfigFactory<ApplicationId, TeTopologyIdConfig> factory = | ||
| 141 | + new ConfigFactory<ApplicationId, TeTopologyIdConfig>(APP_SUBJECT_FACTORY, | ||
| 142 | + TeTopologyIdConfig.class, | ||
| 143 | + "teTopologyId", | ||
| 144 | + true) { | ||
| 145 | + @Override | ||
| 146 | + public TeTopologyIdConfig createConfig() { | ||
| 147 | + return new TeTopologyIdConfig(); | ||
| 148 | + } | ||
| 149 | + }; | ||
| 150 | + private final NetworkConfigListener cfgLister = new InternalConfigListener(); | ||
| 151 | + private ApplicationId appId; | ||
| 152 | + | ||
| 153 | + private DeviceProviderService deviceProviderService; | ||
| 154 | + private LinkProviderService linkProviderService; | ||
| 155 | + | ||
| 156 | + /** | ||
| 157 | + * Activation helper function. | ||
| 158 | + */ | ||
| 159 | + public void activateBasics() { | ||
| 160 | + store.setDelegate(delegate); | ||
| 161 | + eventDispatcher.addSink(TeTopologyEvent.class, listenerRegistry); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + /** | ||
| 165 | + * Deactivation helper function. | ||
| 166 | + */ | ||
| 167 | + public void deactivateBasics() { | ||
| 168 | + store.unsetDelegate(delegate); | ||
| 169 | + eventDispatcher.removeSink(TeTopologyEvent.class); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + @Activate | ||
| 173 | + public void activate() { | ||
| 174 | + activateBasics(); | ||
| 175 | + appId = coreService.registerApplication(APP_NAME); | ||
| 176 | + cfgService.registerConfigFactory(factory); | ||
| 177 | + cfgService.addListener(cfgLister); | ||
| 178 | + | ||
| 179 | + deviceProviderService = deviceProviderRegistry.register(this); | ||
| 180 | + linkProviderService = linkProviderRegistry.register(this); | ||
| 181 | + | ||
| 182 | + //TODO: Needs to add the event listener into LINK and Device subsystem | ||
| 183 | + | ||
| 184 | + log.info("Started"); | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + @Deactivate | ||
| 188 | + public void deactivate() { | ||
| 189 | + deactivateBasics(); | ||
| 190 | + | ||
| 191 | + cfgService.removeListener(cfgLister); | ||
| 192 | + cfgService.unregisterConfigFactory(factory); | ||
| 193 | + | ||
| 194 | + deviceProviderRegistry.unregister(this); | ||
| 195 | + linkProviderRegistry.unregister(this); | ||
| 196 | + | ||
| 197 | + //TODO: Needs to remove the event listener from LINK and Device subsystem | ||
| 198 | + | ||
| 199 | + log.info("Stopped"); | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + @Override | ||
| 203 | + public Networks getNetworks() { | ||
| 204 | + // return a list of the native networks | ||
| 205 | + List<InternalTeNetwork> teNetworks = store.getNetworks(TeTopologyType.NATIVE); | ||
| 206 | + | ||
| 207 | + List<Network> defaultNetworks = new ArrayList<>(); | ||
| 208 | + for (InternalTeNetwork teNetwork : teNetworks) { | ||
| 209 | + defaultNetworks.add(teNetwork); | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + return (new DefaultNetworks(defaultNetworks)); | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + @Override | ||
| 216 | + public Network getNetwork(KeyId networkId) { | ||
| 217 | + return new DefaultNetwork(store.getNetwork(networkId)); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + @Override | ||
| 221 | + public void updateNetwork(Network network) { | ||
| 222 | + store.updateNetwork(new InternalTeNetwork(TeTopologyType.CONFIGURED, new DefaultNetwork(network))); | ||
| 223 | + //TODO: Need to update nodes and links to Device/Link subsystems. | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + @Override | ||
| 227 | + public void removeNetwork(KeyId networkId) { | ||
| 228 | + store.removeNetwork(networkId); | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + @Override | ||
| 232 | + protected TeTopologyProviderService createProviderService(TeTopologyProvider provider) { | ||
| 233 | + return new InternalTopologyProviderService(provider); | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + private class InternalTopologyProviderService | ||
| 237 | + extends AbstractProviderService<TeTopologyProvider> | ||
| 238 | + implements TeTopologyProviderService { | ||
| 239 | + | ||
| 240 | + protected InternalTopologyProviderService(TeTopologyProvider provider) { | ||
| 241 | + super(provider); | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + @Override | ||
| 245 | + public void networkUpdated(Network network) { | ||
| 246 | + // Store received network data into the local TE topology data store | ||
| 247 | + InternalTeNetwork teNetwork = new InternalTeNetwork(TeTopologyType.SUBORDINATE, network); | ||
| 248 | + store.updateNetwork(teNetwork); | ||
| 249 | + | ||
| 250 | + // let's do it here for now | ||
| 251 | + mergeNetworks(); | ||
| 252 | + | ||
| 253 | + //TODO: Store node and link in Device/Link subsystem | ||
| 254 | + //deviceProviderService.deviceConnected(arg0, arg1); | ||
| 255 | + //linkProviderService.linkDetected(arg0); | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + @Override | ||
| 259 | + public void networkRemoved(KeyId networkId) { | ||
| 260 | + store.removeNetwork(networkId); | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + @Override | ||
| 264 | + public void linkUpdated(NetworkLinkKey linkKey, NetworkLink link) { | ||
| 265 | + // Need to check if this is a new link | ||
| 266 | + | ||
| 267 | + //deviceProviderService.deviceConnected(arg0, arg1); | ||
| 268 | + } | ||
| 269 | + | ||
| 270 | + @Override | ||
| 271 | + public void linkRemoved(NetworkLinkKey linkKey) { | ||
| 272 | + // No action is required (TODO: Auto-generated method stub) | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + @Override | ||
| 276 | + public void nodeUpdated(NetworkNodeKey nodeKey, NetworkNode node) { | ||
| 277 | + // Need to check if this is a new node | ||
| 278 | + | ||
| 279 | + // No action is required (TODO: Auto-generated method stub) | ||
| 280 | + } | ||
| 281 | + | ||
| 282 | + @Override | ||
| 283 | + public void nodeRemoved(NetworkNodeKey nodeKey) { | ||
| 284 | + // No action is required (TODO: Auto-generated method stub) | ||
| 285 | + } | ||
| 286 | + | ||
| 287 | + @Override | ||
| 288 | + public void terminationPointUpdated(TerminationPointKey terminationPointKey, | ||
| 289 | + TerminationPoint terminationPoint) { | ||
| 290 | + // No action is required (TODO: Auto-generated method stub) | ||
| 291 | + } | ||
| 292 | + | ||
| 293 | + @Override | ||
| 294 | + public void terminationPointRemoved(TerminationPointKey terminationPointKey) { | ||
| 295 | + // No action is required (TODO: Auto-generated method stub) | ||
| 296 | + } | ||
| 297 | + | ||
| 298 | + } | ||
| 299 | + | ||
| 300 | + private class InternalStoreDelegate implements TeTopologyStoreDelegate { | ||
| 301 | + @Override | ||
| 302 | + public void notify(TeTopologyEvent event) { | ||
| 303 | + if (event != null) { | ||
| 304 | + //post(event); | ||
| 305 | + processEvent(event); | ||
| 306 | + } | ||
| 307 | + } | ||
| 308 | + } | ||
| 309 | + | ||
| 310 | + private void processEvent(TeTopologyEvent event) { | ||
| 311 | + log.info("ProcessEvent {}", event.type().toString()); | ||
| 312 | + | ||
| 313 | + //TODO - partial merge when network is updated | ||
| 314 | + if (event.type() == TeTopologyEvent.Type.NETWORK_ADDED) { | ||
| 315 | + // move network merging to networkUpdated() | ||
| 316 | + //mergeNetworks(); | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + //TODO: Merge node and links from Device/Links subsytems if required. | ||
| 320 | + | ||
| 321 | + post(event); | ||
| 322 | + } | ||
| 323 | + | ||
| 324 | + private void mergeNetworks() { | ||
| 325 | + /* | ||
| 326 | + * Merge all subordinate TE topologies, create a simple merged native topology | ||
| 327 | + * and store it in the topology store. | ||
| 328 | + */ | ||
| 329 | + /* TODO - generate new id based on its provider id + network id */ | ||
| 330 | + KeyId newNetworkId = KeyId.keyId(Long.toString(teTopologyId.providerId()) + "-" + teTopologyId.topologyId()); | ||
| 331 | + store.removeNetwork(newNetworkId); | ||
| 332 | + /* create list of links, nodes and termination points */ | ||
| 333 | + List<NetworkLink> allLinks = new ArrayList<>(); | ||
| 334 | + List<NetworkNode> allNodes = new ArrayList<>(); | ||
| 335 | + List<KeyId> allSupportingNetworkIds = new ArrayList<>(); | ||
| 336 | + | ||
| 337 | + /* translate keys for links/nodes/tps */ | ||
| 338 | + List<InternalTeNetwork> subordNetworks = store.getNetworks(TeTopologyType.SUBORDINATE); | ||
| 339 | + for (InternalTeNetwork network : subordNetworks) { | ||
| 340 | + allSupportingNetworkIds.add(network.networkId()); | ||
| 341 | + | ||
| 342 | + /* create and add new nodes */ | ||
| 343 | + List<NetworkNode> nodes = network.getNodes(); | ||
| 344 | + for (NetworkNode node : nodes) { | ||
| 345 | + | ||
| 346 | + KeyId newNodeId = KeyId.keyId(MDSC_URI_PREFIX + node.nodeId()); | ||
| 347 | + TeNode newTeNode = null; | ||
| 348 | + TeNode origTeNode = node.getTe(); | ||
| 349 | + if (origTeNode != null) { | ||
| 350 | + newTeNode = new TeNode(origTeNode.teNodeId()); | ||
| 351 | + newTeNode.setName(origTeNode.name()); | ||
| 352 | + newTeNode.setAdminStatus(origTeNode.adminStatus()); | ||
| 353 | + newTeNode.setOpStatus(origTeNode.opStatus()); | ||
| 354 | + newTeNode.setAbstract(origTeNode.isAbstract()); | ||
| 355 | + List<ConnectivityMatrix> newConnMatrices = new ArrayList<>(); | ||
| 356 | + | ||
| 357 | + for (ConnectivityMatrix conn : origTeNode.connectivityMatrices()) { | ||
| 358 | + KeyId tpId = conn.from().tpId(); | ||
| 359 | + KeyId newFromTpId = KeyId.keyId(MDSC_URI_PREFIX + tpId); | ||
| 360 | + TerminationPointKey newFrom = new TerminationPointKey(newNetworkId, newNodeId, newFromTpId); | ||
| 361 | + | ||
| 362 | + tpId = conn.to().tpId(); | ||
| 363 | + KeyId newToTpId = KeyId.keyId(MDSC_URI_PREFIX + tpId); | ||
| 364 | + TerminationPointKey newTo = new TerminationPointKey(newNetworkId, newNodeId, newToTpId); | ||
| 365 | + ConnectivityMatrix newConnMatrix = | ||
| 366 | + new ConnectivityMatrix(conn.id(), newFrom, newTo, conn.isAllowed()); | ||
| 367 | + newConnMatrices.add(newConnMatrix); | ||
| 368 | + } | ||
| 369 | + newTeNode.setConnectivityMatrices(newConnMatrices); | ||
| 370 | + newTeNode.setUnderlayTopology(origTeNode.underlayTopology()); | ||
| 371 | + newTeNode.setTunnelTerminationPoints(origTeNode.tunnelTerminationPoints()); | ||
| 372 | + } | ||
| 373 | + List<NetworkNodeKey> supportingNodes = Lists.newArrayList(); | ||
| 374 | + supportingNodes.add(new NetworkNodeKey(network.networkId(), node.nodeId())); | ||
| 375 | + DefaultNetworkNode newNode = | ||
| 376 | + new DefaultNetworkNode(newNodeId, supportingNodes, newTeNode); | ||
| 377 | + List<TerminationPoint> newTps = Lists.newArrayList(); | ||
| 378 | + | ||
| 379 | + List<TerminationPoint> origTps = node.getTerminationPoints(); | ||
| 380 | + if (nonEmpty(origTps)) { | ||
| 381 | + for (TerminationPoint tp : origTps) { | ||
| 382 | + DefaultTerminationPoint newTp = | ||
| 383 | + new DefaultTerminationPoint(KeyId.keyId(MDSC_URI_PREFIX + tp.id())); | ||
| 384 | + List<TerminationPointKey> supportTps = Lists.newArrayList(); | ||
| 385 | + supportTps.add(new TerminationPointKey(network.networkId(), node.nodeId(), tp.id())); | ||
| 386 | + newTp.setSupportingTpIds(supportTps); | ||
| 387 | + newTps.add(newTp); | ||
| 388 | + } | ||
| 389 | + } | ||
| 390 | + newNode.setTerminationPoints(newTps); | ||
| 391 | + allNodes.add(newNode); | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + /* create and add new links */ | ||
| 395 | + List<NetworkLink> links = network.getLinks(); | ||
| 396 | + if (nonEmpty(links)) { | ||
| 397 | + for (NetworkLink link : links) { | ||
| 398 | + KeyId newLinkId = KeyId.keyId(MDSC_URI_PREFIX + link.linkId()); | ||
| 399 | + KeyId k = link.getSource().nodeId(); | ||
| 400 | + KeyId newSourceNodeId = | ||
| 401 | + KeyId.keyId(MDSC_URI_PREFIX + k); | ||
| 402 | + k = link.getSource().tpId(); | ||
| 403 | + KeyId newSourceNodeTpId = | ||
| 404 | + KeyId.keyId(MDSC_URI_PREFIX + k); | ||
| 405 | + k = link.getDestination().nodeId(); | ||
| 406 | + KeyId newDestNodeId = | ||
| 407 | + KeyId.keyId(MDSC_URI_PREFIX + k); | ||
| 408 | + k = link.getDestination().tpId(); | ||
| 409 | + KeyId newDestNodeTpId = | ||
| 410 | + KeyId.keyId(MDSC_URI_PREFIX + k); | ||
| 411 | + TerminationPointKey newSourceNodeTp = | ||
| 412 | + new TerminationPointKey(newNetworkId, newSourceNodeId, newSourceNodeTpId); | ||
| 413 | + TerminationPointKey newDestNodeTp = | ||
| 414 | + new TerminationPointKey(newNetworkId, newDestNodeId, newDestNodeTpId); | ||
| 415 | + | ||
| 416 | + DefaultNetworkLink newLink = new DefaultNetworkLink(newLinkId); | ||
| 417 | + newLink.setSource(newSourceNodeTp); | ||
| 418 | + newLink.setDestination(newDestNodeTp); | ||
| 419 | + List<NetworkLinkKey> supportLinks = Lists.newArrayList(); | ||
| 420 | + supportLinks.add(new NetworkLinkKey(network.networkId(), link.linkId())); | ||
| 421 | + newLink.setSupportingLinkIds(supportLinks); | ||
| 422 | + newLink.setTe(link.getTe()); | ||
| 423 | + | ||
| 424 | + allLinks.add(newLink); | ||
| 425 | + } | ||
| 426 | + } | ||
| 427 | + } | ||
| 428 | + | ||
| 429 | + /* save generated native TE network into the store */ | ||
| 430 | + if (allNodes.size() > 0) { | ||
| 431 | + //TeTopologyId newTopoId = new TeTopologyId(MY_PROVIDER_ID, 0L, NATIVE_TOPOLOGY_ID); | ||
| 432 | + DefaultNetwork nativeDefaultNetwork = | ||
| 433 | + new DefaultNetwork(newNetworkId, allSupportingNetworkIds, allNodes, allLinks, teTopologyId, true); | ||
| 434 | + InternalTeNetwork newTeNetwork = new InternalTeNetwork(TeTopologyType.NATIVE, nativeDefaultNetwork); | ||
| 435 | + store.updateNetwork(newTeNetwork); | ||
| 436 | + } | ||
| 437 | + } | ||
| 438 | + | ||
| 439 | + @Override | ||
| 440 | + public ProviderId id() { | ||
| 441 | + return new ProviderId(IETF_TE_TOPOLOGY_MANAGER, PROVIDER); | ||
| 442 | + } | ||
| 443 | + | ||
| 444 | + private class InternalConfigListener implements NetworkConfigListener { | ||
| 445 | + | ||
| 446 | + @Override | ||
| 447 | + public void event(NetworkConfigEvent event) { | ||
| 448 | + try { | ||
| 449 | + teTopologyId = cfgService.getConfig(appId, TeTopologyIdConfig.class).getTeTopologyId(); | ||
| 450 | + } catch (ConfigException e) { | ||
| 451 | + log.error("Configuration error {}", e); | ||
| 452 | + } | ||
| 453 | + log.info("new teTopologyId is {}", teTopologyId); | ||
| 454 | + } | ||
| 455 | + | ||
| 456 | + @Override | ||
| 457 | + public boolean isRelevant(NetworkConfigEvent event) { | ||
| 458 | + return event.configClass().equals(TeTopologyIdConfig.class) && | ||
| 459 | + (event.type() == CONFIG_ADDED || | ||
| 460 | + event.type() == CONFIG_UPDATED); | ||
| 461 | + } | ||
| 462 | + } | ||
| 463 | + | ||
| 464 | + @Override | ||
| 465 | + public void changePortState(DeviceId arg0, PortNumber arg1, boolean arg2) { | ||
| 466 | + // TODO: This will be implemented if required. | ||
| 467 | + } | ||
| 468 | + | ||
| 469 | + @Override | ||
| 470 | + public boolean isReachable(DeviceId arg0) { | ||
| 471 | + // TODO: This will be implemented if required. | ||
| 472 | + return false; | ||
| 473 | + } | ||
| 474 | + | ||
| 475 | + @Override | ||
| 476 | + public void roleChanged(DeviceId arg0, MastershipRole arg1) { | ||
| 477 | + // TODO: This will be implemented if required. | ||
| 478 | + } | ||
| 479 | + | ||
| 480 | + @Override | ||
| 481 | + public void triggerProbe(DeviceId arg0) { | ||
| 482 | + // TODO: This will be implemented if required. | ||
| 483 | + } | ||
| 484 | + | ||
| 485 | + private Ip4Address assignTeNodeId() { | ||
| 486 | + int value = newTeNodeId.toInt(); | ||
| 487 | + | ||
| 488 | + if (value >= NEW_TE_NODE_ID_END.toInt()) { | ||
| 489 | + value = NEW_TE_NODE_ID_START.toInt(); | ||
| 490 | + } | ||
| 491 | + return Ip4Address.valueOf(value); | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + private static boolean nonEmpty(Collection<?> c) { | ||
| 495 | + return c != null && !c.isEmpty(); | ||
| 496 | + } | ||
| 497 | +} |
apps/tetopology/src/main/java/org/onosproject/tetopology/management/impl/package-info.java
0 → 100644
| 1 | +/** | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * TE Topology Management implementation. | ||
| 19 | + */ | ||
| 20 | +package org.onosproject.tetopology.management.impl; |
-
Please register or login to post a comment