blob: 1407e0c426e8e058422f708e9f8c82f427c5082c [file] [log] [blame]
Yixiao Chen68bfab22016-11-11 11:04:10 -05001/*
2 * Copyright 2016-present 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 */
16package org.onosproject.tetopology.management.impl;
17
18import static java.util.concurrent.Executors.newFixedThreadPool;
19import static org.onlab.util.Tools.groupedThreads;
20import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
21import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
22import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
Yixiao Chen29f06332016-12-07 16:14:29 -050023import static org.onosproject.tetopology.management.api.OptimizationType.NOT_OPTIMIZED;
24import static org.onosproject.tetopology.management.api.TeTopology.BIT_CUSTOMIZED;
25import static org.onosproject.tetopology.management.api.TeTopology.BIT_LEARNT;
26import static org.onosproject.tetopology.management.api.TeTopology.BIT_MERGED;
Yixiao Chen68bfab22016-11-11 11:04:10 -050027import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_ADDED;
28import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_REMOVED;
29import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_UPDATED;
30import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_ADDED;
31import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_REMOVED;
32import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_ADDED;
33import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_REMOVED;
34import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_UPDATED;
35import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_ADDED;
36import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_REMOVED;
37import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_UPDATED;
38import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_ADDED;
39import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_REMOVED;
40import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_UPDATED;
41import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_TOPOLOGY_ADDED;
42import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_TOPOLOGY_REMOVED;
Yixiao Chen29f06332016-12-07 16:14:29 -050043import static org.onosproject.tetopology.management.impl.TeMgrUtil.linkBuilder;
44import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkBuilder;
45import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkLinkKey;
46import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkNodeKey;
47import static org.onosproject.tetopology.management.impl.TeMgrUtil.nodeBuilder;
48import static org.onosproject.tetopology.management.impl.TeMgrUtil.toNetworkId;
49import static org.onosproject.tetopology.management.impl.TeMgrUtil.toNetworkLinkId;
Yixiao Chen68bfab22016-11-11 11:04:10 -050050
51import java.util.BitSet;
52import java.util.List;
53import java.util.Map;
54import java.util.concurrent.BlockingQueue;
55import java.util.concurrent.ExecutorService;
56import java.util.concurrent.LinkedBlockingQueue;
57
58import org.apache.commons.collections.CollectionUtils;
59import org.apache.commons.collections.MapUtils;
60import org.apache.felix.scr.annotations.Activate;
61import org.apache.felix.scr.annotations.Component;
62import org.apache.felix.scr.annotations.Deactivate;
63import org.apache.felix.scr.annotations.Reference;
64import org.apache.felix.scr.annotations.ReferenceCardinality;
65import org.apache.felix.scr.annotations.Service;
66import org.onlab.packet.Ip4Address;
67import org.onosproject.app.ApplicationException;
68import org.onosproject.core.ApplicationId;
69import org.onosproject.core.CoreService;
70import org.onosproject.incubator.net.config.basics.ConfigException;
71import org.onosproject.net.DeviceId;
72import org.onosproject.net.config.ConfigFactory;
73import org.onosproject.net.config.NetworkConfigEvent;
74import org.onosproject.net.config.NetworkConfigListener;
75import org.onosproject.net.config.NetworkConfigRegistry;
76import org.onosproject.net.device.DeviceProviderRegistry;
77import org.onosproject.net.device.DeviceService;
78import org.onosproject.net.link.LinkProviderRegistry;
79import org.onosproject.net.link.LinkService;
80import org.onosproject.net.provider.AbstractListenerProviderRegistry;
81import org.onosproject.net.provider.AbstractProviderService;
82import org.onosproject.tetopology.management.api.CommonTopologyData;
83import org.onosproject.tetopology.management.api.DefaultNetwork;
84import org.onosproject.tetopology.management.api.DefaultNetworks;
85import org.onosproject.tetopology.management.api.DefaultTeTopologies;
86import org.onosproject.tetopology.management.api.DefaultTeTopology;
87import org.onosproject.tetopology.management.api.KeyId;
88import org.onosproject.tetopology.management.api.Network;
89import org.onosproject.tetopology.management.api.Networks;
Yixiao Chen68bfab22016-11-11 11:04:10 -050090import org.onosproject.tetopology.management.api.TeConstants;
91import org.onosproject.tetopology.management.api.TeTopologies;
92import org.onosproject.tetopology.management.api.TeTopology;
93import org.onosproject.tetopology.management.api.TeTopologyEvent;
94import org.onosproject.tetopology.management.api.TeTopologyKey;
95import org.onosproject.tetopology.management.api.TeTopologyListener;
96import org.onosproject.tetopology.management.api.TeTopologyProvider;
97import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
98import org.onosproject.tetopology.management.api.TeTopologyProviderService;
99import org.onosproject.tetopology.management.api.TeTopologyService;
100import org.onosproject.tetopology.management.api.link.CommonLinkData;
101import org.onosproject.tetopology.management.api.link.DefaultTeLink;
102import org.onosproject.tetopology.management.api.link.ExternalLink;
103import org.onosproject.tetopology.management.api.link.LinkBandwidth;
104import org.onosproject.tetopology.management.api.link.NetworkLink;
105import org.onosproject.tetopology.management.api.link.NetworkLinkEventSubject;
106import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
107import org.onosproject.tetopology.management.api.link.TeLink;
108import org.onosproject.tetopology.management.api.link.TeLinkEventSubject;
109import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
110import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
111import org.onosproject.tetopology.management.api.link.TePathAttributes;
112import org.onosproject.tetopology.management.api.link.UnderlayPath;
113import org.onosproject.tetopology.management.api.node.CommonNodeData;
114import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
115import org.onosproject.tetopology.management.api.node.DefaultTeNode;
116import org.onosproject.tetopology.management.api.node.NetworkNode;
117import org.onosproject.tetopology.management.api.node.NetworkNodeEventSubject;
118import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
119import org.onosproject.tetopology.management.api.node.TeNode;
120import org.onosproject.tetopology.management.api.node.TeNodeEventSubject;
121import org.onosproject.tetopology.management.api.node.TeNodeKey;
122import org.onosproject.tetopology.management.api.node.TerminationPoint;
123import org.onosproject.tetopology.management.api.node.TerminationPointKey;
124import org.onosproject.tetopology.management.api.node.TtpKey;
125import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
126import org.slf4j.Logger;
127import org.slf4j.LoggerFactory;
128
129import com.google.common.base.MoreObjects;
130import com.google.common.collect.Lists;
131import com.google.common.collect.Maps;
132
133/**
134 * Implementation of the topology management service.
135 */
136@Component(immediate = true)
137@Service
138public class TeTopologyManager
139 extends AbstractListenerProviderRegistry<TeTopologyEvent, TeTopologyListener,
140 TeTopologyProvider, TeTopologyProviderService>
141 implements TeTopologyService, TeTopologyProviderRegistry {
142 private static final String APP_NAME = "org.onosproject.tetopology";
Yixiao Chen29f06332016-12-07 16:14:29 -0500143 private static final long DEFAULT_PROVIDER_ID = 77777;
Yixiao Chen68bfab22016-11-11 11:04:10 -0500144 private static final long DEFAULT_CLIENT_ID = 0x00L;
145 private long providerId = DEFAULT_PROVIDER_ID;
146 private static final int MAX_THREADS = 1;
Yixiao Chen29f06332016-12-07 16:14:29 -0500147 private static final Ip4Address DEFAULT_TENODE_ID_START = Ip4Address.valueOf("10.10.10.10");
Yixiao Chen68bfab22016-11-11 11:04:10 -0500148 private static final Ip4Address DEFAULT_TENODE_ID_END = Ip4Address.valueOf("250.250.250.250");
149 private Ip4Address teNodeIpStart = DEFAULT_TENODE_ID_START;
150 private Ip4Address teNodeIpEnd = DEFAULT_TENODE_ID_END;
151 private long nextTeNodeId = teNodeIpStart.toInt();
Yixiao Chen29f06332016-12-07 16:14:29 -0500152 private boolean mdsc = true;
153 private static final String MDSC_MODE = "true";
154
Yixiao Chen68bfab22016-11-11 11:04:10 -0500155 private final Logger log = LoggerFactory.getLogger(getClass());
156
157 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
158 protected CoreService coreService;
159
160 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
161 protected NetworkConfigRegistry cfgService;
162
163 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
164 protected DeviceService deviceService;
165
166 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
167 protected LinkService linkService;
168
169 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
170 protected DeviceProviderRegistry deviceProviderRegistry;
171
172 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
173 protected LinkProviderRegistry linkProviderRegistry;
174
175 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
176 public TeTopologyStore store;
177
178 private TeTopologyStoreDelegate delegate = this::post;
179 private final BlockingQueue<TeTopologyEvent> eventQueue = new LinkedBlockingQueue<>();
180 private final BlockingQueue<TeTopologyMapEvent> mapEventQueue = new LinkedBlockingQueue<>();
181 private final ConfigFactory<ApplicationId, TeTopologyConfig> factory =
182 new ConfigFactory<ApplicationId, TeTopologyConfig>(APP_SUBJECT_FACTORY,
183 TeTopologyConfig.class,
184 "teTopologyCfg",
185 false) {
186 @Override
187 public TeTopologyConfig createConfig() {
188 return new TeTopologyConfig();
189 }
190 };
191 private final NetworkConfigListener cfgLister = new InternalConfigListener();
192 private ApplicationId appId;
193 // The topology merged in MDSC
194 private TeTopology mergedTopology = null;
195 private TeTopologyKey mergedTopologyKey;
196 private Network mergedNetwork = null;
197 // Track new TE node id by its source TE node key
198 private Map<TeNodeKey, Long> sourceNewTeNodeIdMap = Maps.newHashMap();
199 // Track the external link keys by the plugId
200 private Map<Long, LinkKeyPair> externalLinkMap = Maps.newHashMap();
201 private ExecutorService executor;
202
203 /**
204 * Activation helper function.
205 */
206 public void activateBasics() {
207 store.setDelegate(delegate);
208 store.setMapEventQueue(mapEventQueue);
Yixiao Chen29f06332016-12-07 16:14:29 -0500209 store.setProviderId(providerId);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500210 eventDispatcher.addSink(TeTopologyEvent.class, listenerRegistry);
211 }
212
213 /**
214 * Deactivation helper function.
215 */
216 public void deactivateBasics() {
217 store.unsetDelegate(delegate);
218 eventDispatcher.removeSink(TeTopologyEvent.class);
219 }
220
221 @Activate
222 public void activate() {
223 activateBasics();
224 appId = coreService.registerApplication(APP_NAME);
225 cfgService.registerConfigFactory(factory);
226 executor = newFixedThreadPool(MAX_THREADS, groupedThreads("onos/tetopology", "build-%d", log));
227
228 cfgService.addListener(cfgLister);
229 executor.execute(new TopologyMergerTask());
230 log.info("Started");
231 }
232
233 @Deactivate
234 public void deactivate() {
235 deactivateBasics();
236 externalLinkMap.clear();
237 cfgService.removeListener(cfgLister);
238 cfgService.unregisterConfigFactory(factory);
239 executor.shutdownNow();
240 executor = null;
241 eventQueue.clear();
242 log.info("Stopped");
243 }
244
245 @Override
246 protected TeTopologyProviderService createProviderService(TeTopologyProvider provider) {
247 return new InternalTopologyProviderService(provider);
248 }
249
250 private class InternalTopologyProviderService
251 extends AbstractProviderService<TeTopologyProvider>
252 implements TeTopologyProviderService {
253
254 protected InternalTopologyProviderService(TeTopologyProvider provider) {
255 super(provider);
256 }
257
258 @Override
259 public void networkUpdated(Network network) {
260 store.updateNetwork(network);
261 }
262
263 @Override
264 public void networkRemoved(KeyId networkId) {
265 store.removeNetwork(networkId);
266 }
267
268 @Override
269 public void linkUpdated(NetworkLinkKey linkKey, NetworkLink link) {
270 store.updateNetworkLink(linkKey, link);
271 }
272
273 @Override
274 public void linkRemoved(NetworkLinkKey linkKey) {
275 store.removeNetworkLink(linkKey);
276 }
277
278 @Override
279 public void nodeUpdated(NetworkNodeKey nodeKey, NetworkNode node) {
280 store.updateNetworkNode(nodeKey, node);
281 }
282
283 @Override
284 public void nodeRemoved(NetworkNodeKey nodeKey) {
285 store.removeNetworkNode(nodeKey);
286 }
287
288 @Override
289 public void terminationPointUpdated(TerminationPointKey terminationPointKey,
290 TerminationPoint terminationPoint) {
291 store.updateTerminationPoint(terminationPointKey, terminationPoint);
292 }
293
294 @Override
295 public void terminationPointRemoved(TerminationPointKey terminationPointKey) {
296 store.removeTerminationPoint(terminationPointKey);
297 }
298 }
299
300 private boolean isCustomizedLearnedTopology(TeTopologyKey key) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500301 if (store.teTopology(key).flags().get(BIT_CUSTOMIZED) &&
302 store.teTopology(key).flags().get(BIT_LEARNT)) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500303 return true;
304 }
305 return false;
306 }
307
308 // Task for merge the learned topology.
309 private class TopologyMergerTask implements Runnable {
310
311 public TopologyMergerTask() {
312 }
313
314 @Override
315 public void run() {
316 try {
317 TeTopologyMapEvent event;
318 while ((event = mapEventQueue.take()) != null) {
319 switch (event.type()) {
320 case TE_TOPOLOGY_ADDED:
321 case TE_TOPOLOGY_UPDATED:
322 TeTopology teTopology = store.teTopology(event.teTopologyKey());
323 post(new TeTopologyEvent(event.type(), teTopology));
Yixiao Chen29f06332016-12-07 16:14:29 -0500324 if (mdsc && event.type() == TE_TOPOLOGY_ADDED &&
325 teTopology.flags().get(BIT_CUSTOMIZED) &&
326 teTopology.flags().get(BIT_LEARNT)) {
327 log.debug("TeTopology to be merged: {}", teTopology);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500328 mergeTopology(teTopology);
329 }
330 break;
331 case TE_TOPOLOGY_REMOVED:
332 post(new TeTopologyEvent(TE_TOPOLOGY_REMOVED,
333 new DefaultTeTopology(event.teTopologyKey(),
334 null, null, null, null)));
335 break;
336 case TE_NODE_ADDED:
337 case TE_NODE_UPDATED:
338 TeNode teNode = store.teNode(event.teNodeKey());
339 post(new TeTopologyEvent(event.type(),
340 new TeNodeEventSubject(event.teNodeKey(), teNode)));
Yixiao Chen29f06332016-12-07 16:14:29 -0500341 if (mdsc && isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500342 updateSourceTeNode(mergedTopology.teNodes(),
343 event.teNodeKey().teTopologyKey(), teNode, true);
344 }
345 break;
346 case TE_NODE_REMOVED:
347 post(new TeTopologyEvent(TE_NODE_REMOVED,
348 new TeNodeEventSubject(event.teNodeKey(), null)));
Yixiao Chen29f06332016-12-07 16:14:29 -0500349 if (mdsc && isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500350 removeSourceTeNode(mergedTopology.teNodes(), event.teNodeKey(), true);
351 }
352 break;
353 case TE_LINK_ADDED:
354 case TE_LINK_UPDATED:
355 TeLink teLink = store.teLink(event.teLinkKey());
356 post(new TeTopologyEvent(event.type(),
357 new TeLinkEventSubject(event.teLinkKey(), teLink)));
Yixiao Chen29f06332016-12-07 16:14:29 -0500358 if (mdsc && isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500359 Map<TeLinkTpKey, TeLink> teLinks = Maps.newHashMap(mergedTopology.teLinks());
360 updateSourceTeLink(teLinks, event.teLinkKey().teTopologyKey(), teLink, true);
361 updateMergedTopology(mergedTopology.teNodes(), teLinks);
362 }
363 break;
364 case TE_LINK_REMOVED:
365 post(new TeTopologyEvent(TE_LINK_REMOVED,
366 new TeLinkEventSubject(event.teLinkKey(), null)));
Yixiao Chen29f06332016-12-07 16:14:29 -0500367 if (mdsc && isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500368 Map<TeLinkTpKey, TeLink> teLinks = Maps.newHashMap(mergedTopology.teLinks());
369 removeSourceTeLink(teLinks, event.teLinkKey(), true);
370 updateMergedTopology(mergedTopology.teNodes(), teLinks);
371 }
372 break;
373 case NETWORK_ADDED:
374 case NETWORK_UPDATED:
375 Network network = store.network(event.networkKey());
376 post(new TeTopologyEvent(event.type(), network));
377 break;
378 case NETWORK_REMOVED:
379 post(new TeTopologyEvent(NETWORK_REMOVED,
380 new DefaultNetwork(event.networkKey(),
381 null, null, null, null, false, null)));
382 break;
383 case NODE_ADDED:
384 case NODE_UPDATED:
385 NetworkNode node = store.networkNode(event.networkNodeKey());
386 post(new TeTopologyEvent(event.type(),
387 new NetworkNodeEventSubject(event.networkNodeKey(), node)));
388 break;
389 case NODE_REMOVED:
390 post(new TeTopologyEvent(NODE_REMOVED,
391 new NetworkNodeEventSubject(event.networkNodeKey(), null)));
392 break;
393 case LINK_ADDED:
394 case LINK_UPDATED:
395 NetworkLink link = store.networkLink(event.networkLinkKey());
396 post(new TeTopologyEvent(event.type(),
397 new NetworkLinkEventSubject(event.networkLinkKey(), link)));
398 break;
399 case LINK_REMOVED:
400 post(new TeTopologyEvent(LINK_REMOVED,
401 new NetworkLinkEventSubject(event.networkLinkKey(), null)));
402 break;
403 default:
404 break;
405 }
406 }
407 } catch (InterruptedException e) {
408 log.warn("TopologyMergerTask is interrupted");
409 } catch (Exception e) {
410 log.warn("Unable to merge topology", e);
411 }
412 }
413 }
414
415 private void removeSourceTeNode(Map<Long, TeNode> teNodes,
416 TeNodeKey srcNodeKey, boolean postEvent) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500417 Long mergedTeNodeId = sourceNewTeNodeIdMap.remove(srcNodeKey);
418 if (mergedTeNodeId == null) {
419 return;
420 }
421 if (teNodes.remove(mergedTeNodeId) != null && postEvent) {
422 TeNodeKey nodeKey = new TeNodeKey(mergedTopologyKey,
423 mergedTeNodeId);
424 post(new TeTopologyEvent(TE_NODE_REMOVED,
425 new TeNodeEventSubject(nodeKey, null)));
426 post(new TeTopologyEvent(NODE_REMOVED,
427 new NetworkNodeEventSubject(TeMgrUtil
428 .networkNodeKey(nodeKey), null)));
429 }
Yixiao Chen68bfab22016-11-11 11:04:10 -0500430 }
431
432 private void updateSourceTeNode(Map<Long, TeNode> teNodes, TeTopologyKey srcTopoKey,
433 TeNode srcNode, boolean postEvent) {
434 TeNodeKey sourceTeNodeId = new TeNodeKey(srcTopoKey, srcNode.teNodeId());
435 Long mergedTeNodeId = sourceNewTeNodeIdMap.get(sourceTeNodeId);
436 boolean addNode = false;
437 if (mergedTeNodeId == null) {
438 // New node
439 addNode = true;
440 mergedTeNodeId = nextTeNodeId;
441 nextTeNodeId++;
442 if (nextTeNodeId >= teNodeIpEnd.toInt()) {
443 nextTeNodeId = teNodeIpStart.toInt();
444 log.warn("TE node Id is wrapped back");
445 }
446 sourceNewTeNodeIdMap.put(sourceTeNodeId, mergedTeNodeId);
447 }
448 TeTopologyKey underlayTopologyId = null; // No underlay
449 TeNodeKey supportTeNodeId = null; // No supporting
450
451 CommonNodeData common = new CommonNodeData(srcNode.name(), srcNode.adminStatus(),
452 srcNode.opStatus(), srcNode.flags()); // No change
453 Map<Long, ConnectivityMatrix> connMatrices = srcNode.connectivityMatrices();
454 List<Long> teLinkIds = srcNode.teLinkIds(); // No change
455 Map<Long, TunnelTerminationPoint> ttps = srcNode.tunnelTerminationPoints();
456 List<Long> teTpIds = srcNode.teTerminationPointIds(); // No change
457 DefaultTeNode newNode = new DefaultTeNode(mergedTeNodeId, underlayTopologyId,
458 supportTeNodeId, sourceTeNodeId, common, connMatrices, teLinkIds,
459 ttps, teTpIds);
460 teNodes.put(mergedTeNodeId, newNode);
461 if (postEvent) {
462 //Post event for the TE node in the merged topology
463 TeNodeKey globalKey = new TeNodeKey(mergedTopologyKey, mergedTeNodeId);
464 post(new TeTopologyEvent(addNode ? TE_NODE_ADDED : TE_NODE_UPDATED,
465 new TeNodeEventSubject(globalKey, newNode)));
466 post(new TeTopologyEvent(addNode ? NODE_ADDED : NODE_UPDATED,
Yixiao Chen29f06332016-12-07 16:14:29 -0500467 new NetworkNodeEventSubject(networkNodeKey(globalKey),
468 nodeBuilder(KeyId.keyId(
469 Ip4Address.valueOf((int) newNode.teNodeId()).toString()),
470 newNode))));
Yixiao Chen68bfab22016-11-11 11:04:10 -0500471 }
472 }
473
474 // Merge TE nodes
475 private void mergeNodes(Map<Long, TeNode> nodes, TeTopology topology) {
476
477 if (!MapUtils.isEmpty(topology.teNodes())) {
478 for (Map.Entry<Long, TeNode> entry : topology.teNodes().entrySet()) {
479 updateSourceTeNode(nodes, topology.teTopologyId(), entry.getValue(),
480 mergedTopology != null);
481 }
482 }
483 }
484
485 // Returns a new TeLink based on an existing TeLink with new attributes
486 private TeLink updateTeLink(TeLinkTpKey newKey, TeLinkTpKey peerTeLinkKey,
487 TeTopologyKey underlayTopologyId, TeLinkTpGlobalKey supportTeLinkId,
488 TeLinkTpGlobalKey sourceTeLinkId, ExternalLink externalLink,
489 TeLink exLink) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500490 UnderlayPath underlayPath = null;
491 if (underlayTopologyId != null &&
492 underlayTopologyId.equals(exLink.underlayTeTopologyId())) {
493 underlayPath = new UnderlayPath(exLink.primaryPath(),
494 exLink.backupPaths(), exLink.tunnelProtectionType(),
495 exLink.sourceTtpId(), exLink.destinationTtpId(),
496 exLink.teTunnelId()
497 );
498 }
499
Yixiao Chen68bfab22016-11-11 11:04:10 -0500500 TePathAttributes teAttributes = new TePathAttributes(exLink.cost(),
501 exLink.delay(), exLink.srlgs());
502 LinkBandwidth bandwidth = new LinkBandwidth(exLink.maxBandwidth(),
503 exLink.availBandwidth(),
504 exLink.maxAvailLspBandwidth(),
505 exLink.minAvailLspBandwidth(),
506 exLink.oduResource());
507 CommonLinkData common = new CommonLinkData(exLink.adminStatus(), exLink.opStatus(),
508 exLink.flags(), exLink.switchingLayer(), exLink.encodingLayer(),
509 externalLink, underlayPath, teAttributes,
510 exLink.administrativeGroup(), exLink.interLayerLocks(),
511 bandwidth);
512 return new DefaultTeLink(newKey, peerTeLinkKey, underlayTopologyId,
513 supportTeLinkId, sourceTeLinkId, common);
514 }
515
516 private class LinkKeyPair {
517 private TeLinkTpKey firstKey;
518 private TeLinkTpKey secondKey;
519
520 public LinkKeyPair(TeLinkTpKey firstKey) {
521 this.firstKey = firstKey;
522 }
523
524 public TeLinkTpKey firstKey() {
525 return firstKey;
526 }
527
528 public void setFirstKey(TeLinkTpKey firstKey) {
529 this.firstKey = firstKey;
530 }
531
532 public TeLinkTpKey secondKey() {
533 return secondKey;
534 }
535
536 public void setSecondKey(TeLinkTpKey secondKey) {
537 this.secondKey = secondKey;
538 }
539
Yixiao Chen29f06332016-12-07 16:14:29 -0500540 public boolean isFirstKey(TeLinkTpKey linkKey) {
541 return firstKey == null ? false : firstKey.equals(linkKey);
542 }
543
544 public boolean isSecondKey(TeLinkTpKey linkKey) {
545 return secondKey == null ? false : secondKey.equals(linkKey);
546 }
547
548 public boolean isEmpty() {
549 return firstKey == null && secondKey == null;
550 }
551
Yixiao Chen68bfab22016-11-11 11:04:10 -0500552 @Override
553 public String toString() {
554 return MoreObjects.toStringHelper(this)
555 .add("firstKey", firstKey)
556 .add("secondKey", secondKey)
557 .toString();
558 }
559 }
560
561 private void removeSourceTeLink(Map<TeLinkTpKey, TeLink> teLinks, TeLinkTpGlobalKey teLinkKey,
562 boolean postEvent) {
563 TeNodeKey sourceTeNodeKey = teLinkKey.teNodeKey();
564 Long newTeNodeId = sourceNewTeNodeIdMap.get(sourceTeNodeKey);
565 if (newTeNodeId == null) {
566 return;
567 }
568 TeLinkTpKey newLinkKey = new TeLinkTpKey(newTeNodeId, teLinkKey.teLinkTpId());
569 TeLink teLink = teLinks.remove(newLinkKey);
570 if (teLink == null) {
571 return;
572 }
573 //Post event
574 if (postEvent) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500575 TeLinkTpGlobalKey globalKey = new TeLinkTpGlobalKey(mergedTopologyKey,
576 newLinkKey);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500577 post(new TeTopologyEvent(TE_LINK_REMOVED,
Yixiao Chen29f06332016-12-07 16:14:29 -0500578 new TeLinkEventSubject(globalKey, null)));
579 post(new TeTopologyEvent(LINK_REMOVED,
580 new NetworkLinkEventSubject(networkLinkKey(globalKey),
581 null)));
Yixiao Chen68bfab22016-11-11 11:04:10 -0500582 }
583
584 if (teLink.externalLink() != null && teLink.externalLink().plugId() != null) {
585 // Update the LinkKeyPair in externalLinkMap
586 LinkKeyPair pair = externalLinkMap.get(teLink.externalLink().plugId());
Yixiao Chen29f06332016-12-07 16:14:29 -0500587 if (pair.isFirstKey(newLinkKey)) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500588 pair.setFirstKey(null);
Yixiao Chen29f06332016-12-07 16:14:29 -0500589 } else if (pair.isSecondKey(newLinkKey)) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500590 pair.setSecondKey(null);
591 }
Yixiao Chen29f06332016-12-07 16:14:29 -0500592 if (pair.isEmpty()) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500593 externalLinkMap.remove(teLink.externalLink().plugId());
594 }
595 }
596 TeLinkTpKey peerTeLinkKey = teLink.peerTeLinkKey();
597 if (peerTeLinkKey != null) {
598 // Update peerLink's peerTeLinkKey to null
599 TeLink peerLink = teLinks.get(peerTeLinkKey);
Yixiao Chen29f06332016-12-07 16:14:29 -0500600 if (peerLink == null || peerLink.peerTeLinkKey() == null) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500601 return;
602 }
603 TeLink newPeerLink = updateTeLink(peerTeLinkKey, null,
604 peerLink.underlayTeTopologyId(), peerLink.supportingTeLinkId(),
605 peerLink.sourceTeLinkId(), peerLink.externalLink(), peerLink);
606 teLinks.put(peerTeLinkKey, newPeerLink);
607 if (postEvent) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500608 TeLinkTpGlobalKey globalKey = new TeLinkTpGlobalKey(mergedTopologyKey,
609 peerTeLinkKey);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500610 post(new TeTopologyEvent(TE_LINK_UPDATED,
Yixiao Chen29f06332016-12-07 16:14:29 -0500611 new TeLinkEventSubject(globalKey,
612 newPeerLink)));
613 post(new TeTopologyEvent(LINK_UPDATED,
614 new NetworkLinkEventSubject(networkLinkKey(globalKey),
615 linkBuilder(toNetworkLinkId(peerTeLinkKey),
616 newPeerLink))));
Yixiao Chen68bfab22016-11-11 11:04:10 -0500617 }
618 }
619 }
620
621 private void updateSourceTeLink(Map<TeLinkTpKey, TeLink> teLinks, TeTopologyKey srcTopoKey,
622 TeLink srcLink, boolean postEvent) {
623 TeNodeKey sourceTeNodeId = new TeNodeKey(srcTopoKey,
624 srcLink.teLinkKey().teNodeId());
625 TeLinkTpKey newKey = new TeLinkTpKey(
626 sourceNewTeNodeIdMap.get(sourceTeNodeId),
627 srcLink.teLinkKey().teLinkTpId());
628 TeLinkTpKey peerTeLinkKey = null;
629 if (srcLink.peerTeLinkKey() != null) {
630 TeNodeKey sourcePeerNode = new TeNodeKey(srcTopoKey,
631 srcLink.peerTeLinkKey().teNodeId());
632 peerTeLinkKey = new TeLinkTpKey(
633 sourceNewTeNodeIdMap.get(sourcePeerNode),
634 srcLink.peerTeLinkKey().teLinkTpId());
635 }
636
637 if (srcLink.externalLink() != null &&
638 srcLink.externalLink().plugId() != null) {
639 // externalLinkKey doesn't have topology Id.
640 // using plugId for now
641 LinkKeyPair pair = externalLinkMap.get(srcLink.externalLink().plugId());
Yixiao Chen29f06332016-12-07 16:14:29 -0500642 if (pair == null) {
643 // Store it in the map
644 externalLinkMap.put(srcLink.externalLink().plugId(),
645 new LinkKeyPair(newKey));
646 } else {
647 if (newKey.equals(pair.firstKey())) {
648 peerTeLinkKey = pair.secondKey();
649 } else if (newKey.equals(pair.secondKey())) {
650 peerTeLinkKey = pair.firstKey();
651 } else if (pair.firstKey() == null) {
652 peerTeLinkKey = pair.secondKey();
Yixiao Chen68bfab22016-11-11 11:04:10 -0500653 pair.setFirstKey(newKey);
Yixiao Chen29f06332016-12-07 16:14:29 -0500654 } else if (pair.secondKey() == null) {
655 peerTeLinkKey = pair.firstKey();
Yixiao Chen68bfab22016-11-11 11:04:10 -0500656 pair.setSecondKey(newKey);
657 }
658
Yixiao Chen29f06332016-12-07 16:14:29 -0500659 if (peerTeLinkKey != null) {
660 TeLink peerLink = teLinks.get(peerTeLinkKey);
661 if (peerLink != null && (peerLink.peerTeLinkKey() == null
662 || !peerLink.peerTeLinkKey().equals(newKey))) {
663 // Update peer Link with local link key
664 TeLink newPeerLink = updateTeLink(peerTeLinkKey, newKey,
665 peerLink.underlayTeTopologyId(),
666 peerLink.supportingTeLinkId(),
667 peerLink.sourceTeLinkId(),
668 peerLink.externalLink(),
669 peerLink);
670 teLinks.put(peerTeLinkKey, newPeerLink);
671 if (postEvent) {
672 TeLinkTpGlobalKey globalKey = new TeLinkTpGlobalKey(mergedTopologyKey,
673 peerTeLinkKey);
674 post(new TeTopologyEvent(TE_LINK_UPDATED,
675 new TeLinkEventSubject(globalKey,
676 newPeerLink)));
677 post(new TeTopologyEvent(LINK_UPDATED,
678 new NetworkLinkEventSubject(
679 networkLinkKey(globalKey),
680 linkBuilder(toNetworkLinkId(peerTeLinkKey),
681 newPeerLink))));
682 }
Yixiao Chen68bfab22016-11-11 11:04:10 -0500683 }
Yixiao Chen29f06332016-12-07 16:14:29 -0500684 }
Yixiao Chen68bfab22016-11-11 11:04:10 -0500685 }
686 }
687
688 TeTopologyKey underlayTopologyId = null; // No underlay
689 TeLinkTpGlobalKey supportTeLinkId = null; // No support
690 // Source link for the new updated link
691 TeLinkTpGlobalKey sourceTeLinkId = new TeLinkTpGlobalKey(srcTopoKey, srcLink.teLinkKey());
692 TeLink updatedLink = updateTeLink(newKey, peerTeLinkKey, underlayTopologyId,
693 supportTeLinkId, sourceTeLinkId,
694 srcLink.externalLink(), srcLink);
695 TeLinkTpGlobalKey newGlobalKey = new TeLinkTpGlobalKey(mergedTopologyKey, newKey);
Yixiao Chen29f06332016-12-07 16:14:29 -0500696 boolean newLink = teLinks.get(newKey) == null ? true : false;
Yixiao Chen68bfab22016-11-11 11:04:10 -0500697 teLinks.put(newKey, updatedLink);
698 if (postEvent) {
699 //Post event
700 post(new TeTopologyEvent(newLink ? TE_LINK_ADDED : TE_LINK_UPDATED,
701 new TeLinkEventSubject(newGlobalKey, updatedLink)));
702 post(new TeTopologyEvent(newLink ? LINK_ADDED : LINK_UPDATED,
Yixiao Chen29f06332016-12-07 16:14:29 -0500703 new NetworkLinkEventSubject(networkLinkKey(newGlobalKey),
704 linkBuilder(toNetworkLinkId(updatedLink.teLinkKey()),
705 updatedLink))));
Yixiao Chen68bfab22016-11-11 11:04:10 -0500706 }
707 }
708
709 // Merge TE links
710 private void mergeLinks(Map<TeLinkTpKey, TeLink> teLinks, TeTopology topology) {
711 if (!MapUtils.isEmpty(topology.teLinks())) {
712 for (Map.Entry<TeLinkTpKey, TeLink> entry : topology.teLinks().entrySet()) {
713 TeLink srcLink = entry.getValue();
714 updateSourceTeLink(teLinks, topology.teTopologyId(), srcLink,
715 mergedTopology != null);
716 }
717 }
718 }
719
720 // Update the merged topology with new TE nodes and links
721 private void updateMergedTopology(Map<Long, TeNode> teNodes, Map<TeLinkTpKey, TeLink> teLinks) {
722 boolean newTopology = mergedTopology == null;
723 BitSet flags = newTopology ? new BitSet(TeConstants.FLAG_MAX_BITS) : mergedTopology.flags();
Yixiao Chen29f06332016-12-07 16:14:29 -0500724 flags.set(BIT_MERGED);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500725 CommonTopologyData commonData = new CommonTopologyData(newTopology ?
Yixiao Chen29f06332016-12-07 16:14:29 -0500726 toNetworkId(mergedTopologyKey) :
Yixiao Chen68bfab22016-11-11 11:04:10 -0500727 mergedTopology.networkId(),
Yixiao Chen29f06332016-12-07 16:14:29 -0500728 NOT_OPTIMIZED,
Yixiao Chen68bfab22016-11-11 11:04:10 -0500729 flags, DeviceId.deviceId("localHost"));
730 mergedTopology = new DefaultTeTopology(mergedTopologyKey, teNodes, teLinks,
731 Long.toString(mergedTopologyKey.topologyId()), commonData);
Yixiao Chen29f06332016-12-07 16:14:29 -0500732 mergedNetwork = networkBuilder(mergedTopology);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500733 log.info("Nodes# {}, Links# {}", mergedTopology.teNodes().size(), mergedTopology.teLinks().size());
734 }
735
736 // Merge the new learned topology
737 private void mergeTopology(TeTopology topology) {
738 boolean newTopology = mergedTopology == null;
739 mergedTopologyKey = newTopology ?
740 new TeTopologyKey(providerId, DEFAULT_CLIENT_ID,
741 store.nextTeTopologyId()) :
742 mergedTopology.teTopologyId();
743
744 Map<Long, TeNode> teNodes = newTopology || mergedTopology.teNodes() == null ?
745 Maps.newHashMap() : Maps.newHashMap(mergedTopology.teNodes());
746 mergeNodes(teNodes, topology);
747 Map<TeLinkTpKey, TeLink> teLinks = newTopology || mergedTopology.teLinks() == null ?
748 Maps.newHashMap() : Maps.newHashMap(mergedTopology.teLinks());
749 mergeLinks(teLinks, topology);
750 updateMergedTopology(teNodes, teLinks);
Yixiao Chen29f06332016-12-07 16:14:29 -0500751 log.debug("mergedTopology {}", mergedTopology);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500752
753 if (newTopology) {
754 // Post events for the merged network topology;
755 post(new TeTopologyEvent(TE_TOPOLOGY_ADDED, mergedTopology));
756 post(new TeTopologyEvent(NETWORK_ADDED, mergedNetwork));
757 }
758 }
759
760 private TeTopologyKey newTeTopologyKey(TeTopology teTopology) {
761 TeTopologyKey key = teTopology.teTopologyId();
762 if (key == null || teTopology.teTopologyIdStringValue() == null) {
763 log.error("Ignoring the non-TE topology");
764 throw new ApplicationException("Missing TE topology ID");
765 }
766 // Get the topologyId numeric value
767 long idValue = key.topologyId();
768 if (idValue == TeConstants.NIL_LONG_VALUE) {
769 if (teTopology.teTopologyIdStringValue() != null) {
770 try {
771 idValue = Long.parseLong(teTopology.teTopologyIdStringValue());
772 } catch (NumberFormatException e) {
773 // Can't get the long value from the string.
774 // Use an assigned id value from local id pool,
775 idValue = store.nextTeTopologyId();
776 }
777 return new TeTopologyKey(key.providerId(), key.clientId(), idValue);
778 }
779 }
780 return null;
781 }
782
783 private class InternalConfigListener implements NetworkConfigListener {
784
785 @Override
786 public void event(NetworkConfigEvent event) {
787 try {
788 providerId = cfgService.getConfig(appId, TeTopologyConfig.class)
789 .providerId();
Yixiao Chen29f06332016-12-07 16:14:29 -0500790 store.setProviderId(providerId);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500791 teNodeIpStart = cfgService.getConfig(appId, TeTopologyConfig.class)
792 .teNodeIpStart();
793 teNodeIpEnd = cfgService.getConfig(appId, TeTopologyConfig.class)
794 .teNodeIpEnd();
Yixiao Chen29f06332016-12-07 16:14:29 -0500795 mdsc = cfgService.getConfig(appId, TeTopologyConfig.class)
796 .mdsc().equalsIgnoreCase(MDSC_MODE);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500797 nextTeNodeId = teNodeIpStart.toInt();
798 } catch (ConfigException e) {
799 log.error("Configuration error {}", e);
800 }
801 }
802
Yixiao Chen29f06332016-12-07 16:14:29 -0500803
Yixiao Chen68bfab22016-11-11 11:04:10 -0500804 @Override
805 public boolean isRelevant(NetworkConfigEvent event) {
806 return event.configClass().equals(TeTopologyConfig.class) &&
807 (event.type() == CONFIG_ADDED ||
Yixiao Chen29f06332016-12-07 16:14:29 -0500808 event.type() == CONFIG_UPDATED);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500809 }
810 }
811
812 @Override
813 public TeTopologies teTopologies() {
814 Map<TeTopologyKey, TeTopology> map;
815 if (MapUtils.isNotEmpty(store.teTopologies().teTopologies())) {
816 map = Maps.newHashMap(store.teTopologies().teTopologies());
817 } else {
818 map = Maps.newHashMap();
819 }
820 if (mergedTopology != null) {
821 map.put(mergedTopologyKey, mergedTopology);
822 }
823 return new DefaultTeTopologies(store.teTopologies().name(), map);
824 }
825
826 @Override
827 public TeTopology teTopology(TeTopologyKey topologyId) {
828 if (mergedTopology != null &&
829 topologyId.equals(mergedTopologyKey)) {
830 return mergedTopology;
831 }
832 return store.teTopology(topologyId);
833 }
834
835 @Override
836 public TeTopology mergedTopology() {
837 return mergedTopology;
838 }
839
840 @Override
841 public void updateTeTopology(TeTopology teTopology) {
842 TeTopologyKey newKey = null;
843 try {
844 newKey = newTeTopologyKey(teTopology);
845 } catch (ApplicationException e) {
846 log.error("Ignoring the non-TE topology");
847 return;
848 }
849
850 // TE topology is updated here from other APP or NBI, the flag
851 // BIT_CUSTOMIZED or BIT_MERGED should be set.
852 BitSet flags = teTopology.flags();
853 if (flags == null ||
Yixiao Chen29f06332016-12-07 16:14:29 -0500854 !(flags.get(BIT_CUSTOMIZED) || flags.get(BIT_MERGED))) {
Yixiao Chen68bfab22016-11-11 11:04:10 -0500855 log.error("TE topology flags {} are not set properly", flags);
856 return;
857 }
858
859 if (newKey != null) {
860 DefaultTeTopology newTopology = new DefaultTeTopology(
861 newKey == null ? teTopology.teTopologyId() : newKey,
862 teTopology.teNodes(), teTopology.teLinks(),
863 teTopology.teTopologyIdStringValue(), new CommonTopologyData(teTopology));
864 // Update with new data
865 store.updateTeTopology(newTopology);
866 } else {
867 store.updateTeTopology(teTopology);
868 }
869 }
870
871 @Override
872 public void removeTeTopology(TeTopologyKey topologyId) {
873 store.removeTeTopology(topologyId);
874 }
875
876 @Override
877 public Networks networks() {
878 List<Network> networks;
879 if (CollectionUtils.isNotEmpty(store.networks())) {
880 networks = Lists.newArrayList(store.networks());
881 } else {
882 networks = Lists.newArrayList();
883 }
884 if (mergedNetwork != null) {
885 networks.add(mergedNetwork);
886 }
887 return new DefaultNetworks(networks);
888 }
889
890 @Override
891 public Network network(KeyId networkId) {
892 if (mergedNetwork != null &&
893 mergedNetwork.networkId().equals(networkId)) {
894 return mergedNetwork;
895 }
896 return store.network(networkId);
897 }
898
899 @Override
900 public void updateNetwork(Network network) {
901 // TODO: This will be implemented if required.
902 }
903
904 @Override
905 public void removeNetwork(KeyId networkId) {
906 // TODO: This will be implemented if required.
907 }
908
909 @Override
910 public TeNode teNode(TeNodeKey nodeId) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500911 return nodeId.teTopologyKey().equals(mergedTopologyKey) ?
912 mergedTopology.teNode(nodeId.teNodeId()) :
913 store.teNode(nodeId);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500914 }
915
916 @Override
917 public TeLink teLink(TeLinkTpGlobalKey linkId) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500918 return linkId.teTopologyKey().equals(mergedTopologyKey) ?
919 mergedTopology.teLink(linkId.teLinkTpKey()) :
920 store.teLink(linkId);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500921 }
922
923 @Override
924 public TunnelTerminationPoint tunnelTerminationPoint(TtpKey ttpId) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500925 return ttpId.teTopologyKey().equals(mergedTopologyKey) ?
926 mergedTopology.teNode(ttpId.teNodeId()).tunnelTerminationPoint(ttpId.ttpId()) :
927 store.tunnelTerminationPoint(ttpId);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500928 }
929
930 @Override
931 public KeyId networkId(TeTopologyKey teTopologyKey) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500932 return teTopologyKey.equals(mergedTopologyKey) ?
933 mergedNetwork.networkId() :
934 store.networkId(teTopologyKey);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500935 }
936
937 @Override
938 public NetworkNodeKey nodeKey(TeNodeKey teNodeKey) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500939 return teNodeKey.teTopologyKey().equals(mergedTopologyKey) ?
940 networkNodeKey(teNodeKey) :
941 store.nodeKey(teNodeKey);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500942 }
943
944 @Override
945 public NetworkLinkKey linkKey(TeLinkTpGlobalKey teLinkKey) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500946 return teLinkKey.teTopologyKey().equals(mergedTopologyKey) ?
947 networkLinkKey(teLinkKey) :
948 store.linkKey(teLinkKey);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500949 }
950
951 @Override
952 public TerminationPointKey terminationPointKey(TeLinkTpGlobalKey teTpKey) {
Yixiao Chen29f06332016-12-07 16:14:29 -0500953 return teTpKey.teTopologyKey().equals(mergedTopologyKey) ?
954 new TerminationPointKey(networkNodeKey(teTpKey.teNodeKey()),
955 KeyId.keyId(Long.toString(teTpKey.teLinkTpId()))) :
956 store.terminationPointKey(teTpKey);
Yixiao Chen68bfab22016-11-11 11:04:10 -0500957 }
958}