2 * Copyright (c) 2015 Huawei, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
9 package org.opendaylight.nemo.intent.computation;
\r
11 import com.google.common.base.Optional;
\r
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
\r
13 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
\r
14 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
\r
15 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
\r
16 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
\r
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
\r
18 import org.opendaylight.nemo.intent.algorithm.Edge;
\r
19 import org.opendaylight.nemo.intent.algorithm.RoutingAlgorithm;
\r
20 import org.opendaylight.nemo.intent.algorithm.Vertex;
\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.PhysicalNetwork;
\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalLinks;
\r
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalNodes;
\r
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.PhysicalPaths;
\r
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.links.PhysicalLink;
\r
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.nodes.PhysicalNode;
\r
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPath;
\r
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.network.physical.paths.PhysicalPathBuilder;
\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLinkBuilder;
\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalLinkId;
\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalNodeId;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nemo.engine.common.rev151010.PhysicalPathId;
\r
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
\r
34 import org.opendaylight.yangtools.yang.binding.DataObject;
\r
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
\r
36 import org.slf4j.Logger;
\r
37 import org.slf4j.LoggerFactory;
\r
40 import java.util.concurrent.ExecutionException;
\r
43 * The physical network computation unit implements the following functions:
\r
44 * (1) Maintain the underlying physical network topology information through
\r
45 * subscribing from the data store.
\r
46 * (2) Provide the tunnel computation with SLA constraints to the virtual
\r
47 * network mapping computation unit.
\r
49 * @author Zhigang Ji
\r
51 public class PNComputationUnit implements AutoCloseable {
\r
52 private static final Logger LOG = LoggerFactory.getLogger(PNComputationUnit.class);
\r
54 private final DataBroker dataBroker;
\r
57 * The routing algorithm instance.
\r
59 private RoutingAlgorithm routingAlgorithm;
\r
62 * The registration for the physical node change listener.
\r
64 private ListenerRegistration<DataChangeListener> physicalNodeChangeListenerReg;
\r
67 * The registration for the physical link change listener.
\r
69 private ListenerRegistration<DataChangeListener> physicalLinkChangeListenerReg;
\r
72 * The registration for the physical path change listener.
\r
74 private ListenerRegistration<DataChangeListener> physicalPathChangeListenerReg;
\r
76 public PNComputationUnit(DataBroker dataBroker) {
\r
79 this.dataBroker = dataBroker;
\r
80 routingAlgorithm = new RoutingAlgorithm();
\r
82 InstanceIdentifier<PhysicalNode> physicalNodeIid = InstanceIdentifier
\r
83 .builder(PhysicalNetwork.class)
\r
84 .child(PhysicalNodes.class)
\r
85 .child(PhysicalNode.class)
\r
87 InstanceIdentifier<PhysicalLink> physicalLinkIid = InstanceIdentifier
\r
88 .builder(PhysicalNetwork.class)
\r
89 .child(PhysicalLinks.class)
\r
90 .child(PhysicalLink.class)
\r
92 InstanceIdentifier<PhysicalPath> physicalPathIid = InstanceIdentifier
\r
93 .builder(PhysicalNetwork.class)
\r
94 .child(PhysicalPaths.class)
\r
95 .child(PhysicalPath.class)
\r
98 physicalNodeChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
\r
99 physicalNodeIid, new PhysicalNodeChangeListener(), DataChangeScope.BASE);
\r
100 physicalLinkChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
\r
101 physicalLinkIid, new PhysicalLinkChangeListener(), DataChangeScope.BASE);
\r
102 physicalPathChangeListenerReg = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
\r
103 physicalPathIid, new PhysicalPathChangeListener(), DataChangeScope.BASE);
\r
105 ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();
\r
107 InstanceIdentifier<PhysicalNodes> physicalNodesIid = InstanceIdentifier
\r
108 .builder(PhysicalNetwork.class)
\r
109 .child(PhysicalNodes.class)
\r
111 Optional<PhysicalNodes> result;
\r
114 result = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalNodesIid).get();
\r
115 } catch ( InterruptedException | ExecutionException exception ) {
\r
116 throw new RuntimeException("Can not read the physical nodes.");
\r
119 if ( result.isPresent() ) {
\r
120 PhysicalNodes physicalNodes = result.get();
\r
123 for ( PhysicalNode physicalNode : physicalNodes.getPhysicalNode() ) {
\r
124 vertex = new Vertex(physicalNode.getNodeId().getValue());
\r
125 routingAlgorithm.addVertex(vertex);
\r
129 InstanceIdentifier<PhysicalLinks> physicalLinksIid = InstanceIdentifier
\r
130 .builder(PhysicalNetwork.class)
\r
131 .child(PhysicalLinks.class)
\r
133 Optional<PhysicalLinks> result1;
\r
136 result1 = readOnlyTransaction.read(LogicalDatastoreType.OPERATIONAL, physicalLinksIid).get();
\r
137 } catch ( InterruptedException | ExecutionException exception ) {
\r
138 throw new RuntimeException("Can not read the physical links.");
\r
141 if ( result1.isPresent() ) {
\r
142 PhysicalLinks physicalLinks = result1.get();
\r
145 for ( PhysicalLink physicalLink : physicalLinks.getPhysicalLink() ) {
\r
146 edge = new Edge(physicalLink.getLinkId().getValue(), physicalLink.getSrcNodeId().getValue(),
\r
147 physicalLink.getDestNodeId().getValue(), physicalLink.getMetric(),
\r
148 physicalLink.getBandwidth());
\r
149 routingAlgorithm.addEdge(edge);
\r
153 LOG.debug("Initialized the physical network computation unit.");
\r
159 * Compute a shortest physical path from the given source vertex to
\r
160 * target one without any constraint.
\r
162 * @param source The given source physical node id.
\r
163 * @param target The given target physical node id.
\r
164 * @return The physical path if successful,or null otherwise.
\r
166 protected PhysicalPath computePath(PhysicalNodeId source, PhysicalNodeId target) {
\r
167 List<Edge> edges = routingAlgorithm.computePath(routingAlgorithm.getVertex(source.getValue()),
\r
168 routingAlgorithm.getVertex(target.getValue()));
\r
170 if ( null == edges || edges.isEmpty() ) {
\r
174 List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink> physicalLinks =
\r
175 new ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink>(edges.size());
\r
176 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink;
\r
180 for ( Edge edge : edges ) {
\r
181 physicalLink = new PhysicalLinkBuilder()
\r
182 .setLinkId(new PhysicalLinkId(edge.getId()))
\r
183 .setOrder((long) physicalLinks.size())
\r
185 physicalLinks.add(physicalLink);
\r
187 metric += edge.getMetric();
\r
188 // delay += edge.getDelay();
\r
191 PhysicalPath physicalPath = new PhysicalPathBuilder()
\r
192 .setPathId(new PhysicalPathId(UUID.randomUUID().toString()))
\r
193 .setPhysicalLink(physicalLinks)
\r
199 return physicalPath;
\r
203 * Compute a shortest physical path with the given bandwidth from the
\r
204 * given source vertex to target one.
\r
206 * @param source The given source physical node id.
\r
207 * @param target The given target physical node id.
\r
208 * @param bandwidth The given bandwidth for the physical path.
\r
209 * @return The physical path if successful,or null otherwise.
\r
211 protected PhysicalPath computePath(PhysicalNodeId source, PhysicalNodeId target, long bandwidth) {
\r
212 List<Edge> edges = routingAlgorithm.computePath(routingAlgorithm.getVertex(source.getValue()),
\r
213 routingAlgorithm.getVertex(target.getValue()), bandwidth);
\r
215 if ( null == edges || edges.isEmpty() ) {
\r
219 List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink> physicalLinks =
\r
220 new ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink>(edges.size());
\r
221 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink physicalLink;
\r
225 for ( Edge edge : edges ) {
\r
226 edge.setBandwidth(edge.getBandwidth() - bandwidth);
\r
227 routingAlgorithm.updateEdge(edge);
\r
229 physicalLink = new PhysicalLinkBuilder()
\r
230 .setLinkId(new PhysicalLinkId(edge.getId()))
\r
231 .setOrder((long) physicalLinks.size())
\r
233 physicalLinks.add(physicalLink);
\r
235 metric += edge.getMetric();
\r
236 // delay += edge.getDelay();
\r
239 PhysicalPath physicalPath = new PhysicalPathBuilder()
\r
240 .setPathId(new PhysicalPathId(UUID.randomUUID().toString()))
\r
241 .setPhysicalLink(physicalLinks)
\r
243 .setBandwidth(bandwidth)
\r
247 return physicalPath;
\r
251 public void close() throws Exception {
\r
252 if ( null != physicalNodeChangeListenerReg ) {
\r
253 physicalNodeChangeListenerReg.close();
\r
256 if ( null != physicalLinkChangeListenerReg ) {
\r
257 physicalLinkChangeListenerReg.close();
\r
260 if ( null != physicalPathChangeListenerReg ) {
\r
261 physicalPathChangeListenerReg.close();
\r
268 * A listener to change events related to physical nodes being
\r
269 * added, removed or updated.
\r
271 * @author Zhigang Ji
\r
273 private class PhysicalNodeChangeListener implements DataChangeListener {
\r
275 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
\r
276 if ( null == change ) {
\r
280 Map<InstanceIdentifier<?>, DataObject> createdData = change.getCreatedData();
\r
282 if ( null != createdData && !createdData.isEmpty() ) {
\r
283 PhysicalNode physicalNode;
\r
286 for ( DataObject dataObject : createdData.values() ) {
\r
287 if ( dataObject instanceof PhysicalNode ) {
\r
288 physicalNode = (PhysicalNode)dataObject;
\r
289 vertex = new Vertex(physicalNode.getNodeId().getValue());
\r
291 routingAlgorithm.addVertex(vertex);
\r
296 Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();
\r
297 Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();
\r
299 if ( null != removedPaths && !removedPaths.isEmpty() ) {
\r
300 DataObject dataObject;
\r
302 for ( InstanceIdentifier<?> instanceId : removedPaths ) {
\r
303 dataObject = originalData.get(instanceId);
\r
305 if ( null != dataObject && dataObject instanceof PhysicalNode ) {
\r
306 routingAlgorithm.removeVertex(((PhysicalNode)dataObject).getNodeId().getValue());
\r
316 * A listener to change events related to physical links being
\r
317 * added, removed or updated.
\r
319 * @author Zhigang Ji
\r
321 private class PhysicalLinkChangeListener implements DataChangeListener {
\r
323 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
\r
324 if ( null == change ) {
\r
328 Map<InstanceIdentifier<?>, DataObject> createdData = change.getCreatedData();
\r
330 if ( null != createdData && !createdData.isEmpty() ) {
\r
331 PhysicalLink physicalLink;
\r
334 for ( DataObject dataObject : createdData.values() ) {
\r
335 if ( dataObject instanceof PhysicalLink ) {
\r
336 physicalLink = (PhysicalLink)dataObject;
\r
337 edge = new Edge(physicalLink.getLinkId().getValue(), physicalLink.getSrcNodeId().getValue(),
\r
338 physicalLink.getDestNodeId().getValue(), physicalLink.getMetric(),
\r
339 physicalLink.getBandwidth());
\r
341 routingAlgorithm.addEdge(edge);
\r
346 Map<InstanceIdentifier<?>, DataObject> updatedData = change.getUpdatedData();
\r
348 if ( null != updatedData && !updatedData.isEmpty() ) {
\r
349 PhysicalLink physicalLink;
\r
352 for ( DataObject dataObject : updatedData.values() ) {
\r
353 if ( dataObject instanceof PhysicalLink ) {
\r
354 physicalLink = (PhysicalLink)dataObject;
\r
355 edge = new Edge(physicalLink.getLinkId().getValue(), physicalLink.getSrcNodeId().getValue(),
\r
356 physicalLink.getDestNodeId().getValue(), physicalLink.getMetric(),
\r
357 physicalLink.getBandwidth());
\r
359 routingAlgorithm.updateEdge(edge);
\r
364 Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();
\r
365 Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();
\r
367 if ( null != removedPaths && !removedPaths.isEmpty() ) {
\r
368 DataObject dataObject;
\r
370 for ( InstanceIdentifier<?> instanceId : removedPaths ) {
\r
371 dataObject = originalData.get(instanceId);
\r
373 if ( null != dataObject && dataObject instanceof PhysicalLink ) {
\r
374 routingAlgorithm.removeEdge(((PhysicalLink)dataObject).getLinkId().getValue());
\r
384 * A listener to change events related to physical paths being
\r
385 * added, removed or updated.
\r
387 * @author Zhigang Ji
\r
389 private class PhysicalPathChangeListener implements DataChangeListener {
\r
391 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
\r
392 if ( null == change ) {
\r
396 Map<InstanceIdentifier<?>, DataObject> originalData = change.getOriginalData();
\r
397 Set<InstanceIdentifier<?>> removedPaths = change.getRemovedPaths();
\r
399 if ( null != removedPaths && !removedPaths.isEmpty() ) {
\r
400 DataObject dataObject;
\r
401 PhysicalPath physicalPath;
\r
403 List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink> physicalLinks;
\r
406 for ( InstanceIdentifier<?> instanceId : removedPaths ) {
\r
407 dataObject = originalData.get(instanceId);
\r
409 if ( null != dataObject && dataObject instanceof PhysicalPath ) {
\r
410 physicalPath = (PhysicalPath)dataObject;
\r
411 bandwidth = physicalPath.getBandwidth();
\r
413 if ( 0 < bandwidth ) {
\r
414 physicalLinks = physicalPath.getPhysicalLink();
\r
416 if ( null != physicalLinks && !physicalLinks.isEmpty() ) {
\r
417 for ( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.generic.physical.network.rev151010.physical.path.instance.PhysicalLink
\r
418 physicalLink : physicalLinks ) {
\r
419 edge = routingAlgorithm.getEdge(physicalLink.getLinkId().getValue());
\r
421 if ( null != edge ) {
\r
422 edge.setBandwidth(edge.getBandwidth() + bandwidth);
\r
423 routingAlgorithm.updateEdge(edge);
\r