blob: 3860dee5523d4956f9fba387e88155631ff54615 [file] [log] [blame]
Brian Stankefb61df42016-07-25 11:47:51 -04001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Brian Stankefb61df42016-07-25 11:47:51 -04003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
yoonseon214963b2016-11-21 15:41:07 -080017package org.onosproject.incubator.net.virtual.impl.provider;
Brian Stankefb61df42016-07-25 11:47:51 -040018
Brian Stankefb61df42016-07-25 11:47:51 -040019import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
yoonseon6b972c32016-12-06 16:45:03 -080020import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
21import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
22import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Brian Stankefb61df42016-07-25 11:47:51 -040023import org.onosproject.net.ConnectPoint;
24import org.onosproject.net.Link;
25import org.onosproject.net.Path;
26import org.onosproject.net.link.LinkEvent;
27import org.onosproject.net.provider.AbstractProvider;
28import org.onosproject.net.topology.Topology;
29import org.onosproject.net.topology.TopologyCluster;
30import org.onosproject.net.topology.TopologyEvent;
31import org.onosproject.net.topology.TopologyListener;
32import org.onosproject.net.topology.TopologyService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070033import org.osgi.service.component.annotations.Activate;
34import org.osgi.service.component.annotations.Component;
35import org.osgi.service.component.annotations.Deactivate;
36import org.osgi.service.component.annotations.Reference;
37import org.osgi.service.component.annotations.ReferenceCardinality;
Brian Stankefb61df42016-07-25 11:47:51 -040038import org.slf4j.Logger;
39
40import java.util.HashSet;
41import java.util.Set;
Thomas Vachuskac8187a02016-08-08 11:56:24 -070042import java.util.concurrent.ExecutorService;
Brian Stankefb61df42016-07-25 11:47:51 -040043
Thomas Vachuskac8187a02016-08-08 11:56:24 -070044import static java.util.concurrent.Executors.newSingleThreadExecutor;
45import static org.onlab.util.Tools.groupedThreads;
Brian Stankefb61df42016-07-25 11:47:51 -040046import static org.slf4j.LoggerFactory.getLogger;
47
48/**
49 * Virtual network topology provider.
50 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070051@Component(service = VirtualNetworkProvider.class)
yoonseon214963b2016-11-21 15:41:07 -080052public class DefaultVirtualNetworkProvider
53 extends AbstractProvider implements VirtualNetworkProvider {
Brian Stankefb61df42016-07-25 11:47:51 -040054
yoonseon214963b2016-11-21 15:41:07 -080055 private final Logger log = getLogger(DefaultVirtualNetworkProvider.class);
Brian Stankefb61df42016-07-25 11:47:51 -040056
Ray Milkeyd84f89b2018-08-17 14:54:17 -070057 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Brian Stankefb61df42016-07-25 11:47:51 -040058 protected VirtualNetworkProviderRegistry providerRegistry;
59
60 private VirtualNetworkProviderService providerService;
61
Ray Milkeyd84f89b2018-08-17 14:54:17 -070062 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Brian Stankefb61df42016-07-25 11:47:51 -040063 protected TopologyService topologyService;
64
65 protected TopologyListener topologyListener = new InternalTopologyListener();
66
Thomas Vachuskac8187a02016-08-08 11:56:24 -070067 private ExecutorService executor;
68
Brian Stankefb61df42016-07-25 11:47:51 -040069 /**
70 * Default constructor.
71 */
yoonseon214963b2016-11-21 15:41:07 -080072 public DefaultVirtualNetworkProvider() {
Brian Stankefb61df42016-07-25 11:47:51 -040073 super(DefaultVirtualLink.PID);
74 }
75
76 @Activate
77 public void activate() {
Thomas Vachuskac8187a02016-08-08 11:56:24 -070078 executor = newSingleThreadExecutor(groupedThreads("onos/vnet", "provider", log));
Brian Stankefb61df42016-07-25 11:47:51 -040079 providerService = providerRegistry.register(this);
80 topologyService.addListener(topologyListener);
Brian Stankefb61df42016-07-25 11:47:51 -040081 log.info("Started");
82 }
83
84 @Deactivate
85 public void deactivate() {
86 topologyService.removeListener(topologyListener);
Thomas Vachuskad13e4a42016-08-08 14:39:51 -070087 executor.shutdownNow();
Thomas Vachuskac8187a02016-08-08 11:56:24 -070088 executor = null;
Brian Stankefb61df42016-07-25 11:47:51 -040089 providerRegistry.unregister(this);
90 providerService = null;
91 log.info("Stopped");
92 }
93
94 @Override
95 public boolean isTraversable(ConnectPoint src, ConnectPoint dst) {
96 final boolean[] foundSrc = new boolean[1];
97 final boolean[] foundDst = new boolean[1];
98 Topology topology = topologyService.currentTopology();
99 Set<Path> paths = topologyService.getPaths(topology, src.deviceId(), dst.deviceId());
100 paths.forEach(path -> {
101 foundDst[0] = false;
102 foundSrc[0] = false;
103 // Traverse the links in each path to determine if both the src and dst connection
104 // point are in the path, if so then this src/dst pair are traversable.
105 path.links().forEach(link -> {
106 if (link.src().equals(src)) {
107 foundSrc[0] = true;
108 }
109 if (link.dst().equals(dst)) {
110 foundDst[0] = true;
111 }
112 });
113 if (foundSrc[0] && foundDst[0]) {
114 return;
115 }
116 });
117 return foundSrc[0] && foundDst[0];
118 }
119
Brian Stankefb61df42016-07-25 11:47:51 -0400120 /**
121 * Returns a set of set of interconnected connect points in the default topology.
122 * The inner set represents the interconnected connect points, and the outerset
123 * represents separate clusters.
124 *
125 * @param topology the default topology
126 * @return set of set of interconnected connect points.
127 */
yoonseon214963b2016-11-21 15:41:07 -0800128 public Set<Set<ConnectPoint>> getConnectPoints(Topology topology) {
Brian Stankefb61df42016-07-25 11:47:51 -0400129 Set<Set<ConnectPoint>> clusters = new HashSet<>();
130 Set<TopologyCluster> topologyClusters = topologyService.getClusters(topology);
131 topologyClusters.forEach(topologyCluster -> {
132 Set<ConnectPoint> connectPointSet = new HashSet<>();
yoonseon214963b2016-11-21 15:41:07 -0800133 Set<Link> clusterLinks =
134 topologyService.getClusterLinks(topology, topologyCluster);
Brian Stankefb61df42016-07-25 11:47:51 -0400135 clusterLinks.forEach(link -> {
136 connectPointSet.add(link.src());
137 connectPointSet.add(link.dst());
138 });
139 if (!connectPointSet.isEmpty()) {
140 clusters.add(connectPointSet);
141 }
142 });
143 return clusters;
144 }
145
146 /**
147 * Topology event listener.
148 */
149 private class InternalTopologyListener implements TopologyListener {
150 @Override
151 public void event(TopologyEvent event) {
Thomas Vachuskac8187a02016-08-08 11:56:24 -0700152 // Perform processing off the listener thread.
yoonseon214963b2016-11-21 15:41:07 -0800153 executor.submit(() -> providerService
154 .topologyChanged(getConnectPoints(event.subject())));
Brian Stankefb61df42016-07-25 11:47:51 -0400155 }
156
157 @Override
158 public boolean isRelevant(TopologyEvent event) {
Thomas Vachuskac8187a02016-08-08 11:56:24 -0700159 return event.type() == TopologyEvent.Type.TOPOLOGY_CHANGED &&
160 event.reasons().stream().anyMatch(reason -> reason instanceof LinkEvent);
Brian Stankefb61df42016-07-25 11:47:51 -0400161 }
162 }
163}