blob: 358237a2d9f44d529e8e0794868eeb695b34c391 [file] [log] [blame]
Aihua Guoeb9b3782016-09-09 01:11:40 -04001/*
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 */
16package org.onosproject.tetopology.management.impl;
17
18import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
19import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
20import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
21
22import java.util.ArrayList;
23import java.util.List;
24import java.util.Collection;
25
26import org.apache.felix.scr.annotations.Activate;
27import org.apache.felix.scr.annotations.Component;
28import org.apache.felix.scr.annotations.Deactivate;
29import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
31import org.apache.felix.scr.annotations.Service;
32import org.onlab.packet.Ip4Address;
33import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.incubator.net.config.basics.ConfigException;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.MastershipRole;
38import org.onosproject.net.PortNumber;
39import org.onosproject.net.config.ConfigFactory;
40import org.onosproject.net.config.NetworkConfigEvent;
41import org.onosproject.net.config.NetworkConfigListener;
42import org.onosproject.net.config.NetworkConfigRegistry;
43import org.onosproject.net.device.DeviceProvider;
44import org.onosproject.net.device.DeviceProviderRegistry;
45import org.onosproject.net.device.DeviceProviderService;
46import org.onosproject.net.device.DeviceService;
47import org.onosproject.net.link.LinkProvider;
48import org.onosproject.net.link.LinkProviderRegistry;
49import org.onosproject.net.link.LinkProviderService;
50import org.onosproject.net.link.LinkService;
51import org.onosproject.net.provider.AbstractListenerProviderRegistry;
52import org.onosproject.net.provider.AbstractProviderService;
53import org.onosproject.net.provider.ProviderId;
54import org.onosproject.tetopology.management.api.DefaultNetwork;
55import org.onosproject.tetopology.management.api.DefaultNetworks;
56import org.onosproject.tetopology.management.api.InternalTeNetwork;
57import org.onosproject.tetopology.management.api.KeyId;
58import org.onosproject.tetopology.management.api.Network;
59import org.onosproject.tetopology.management.api.Networks;
60import org.onosproject.tetopology.management.api.TeTopologyEvent;
61import org.onosproject.tetopology.management.api.TeTopologyId;
62import org.onosproject.tetopology.management.api.TeTopologyListener;
63import org.onosproject.tetopology.management.api.TeTopologyProvider;
64import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
65import org.onosproject.tetopology.management.api.TeTopologyProviderService;
66import org.onosproject.tetopology.management.api.TeTopologyService;
67import org.onosproject.tetopology.management.api.TeTopologyStore;
68import org.onosproject.tetopology.management.api.TeTopologyStoreDelegate;
69import org.onosproject.tetopology.management.api.TeTopologyType;
70import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
71import org.onosproject.tetopology.management.api.link.NetworkLink;
72import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
73import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
74import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
75import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
76import org.onosproject.tetopology.management.api.node.NetworkNode;
77import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
78import org.onosproject.tetopology.management.api.node.TeNode;
79import org.onosproject.tetopology.management.api.node.TerminationPoint;
80import org.onosproject.tetopology.management.api.node.TerminationPointKey;
81import org.slf4j.Logger;
82import org.slf4j.LoggerFactory;
83
84import com.google.common.collect.Lists;
85
86/**
87 * Implementation of the topology management service.
88 */
89@Component(immediate = true)
90@Service
91public 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}