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