blob: 8f7c55e52e2ea391e15b6f3b839f6f8d5435b5f3 [file] [log] [blame]
Brian Stankefb61df42016-07-25 11:47:51 -04001/*
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 */
16
yoonseon214963b2016-11-21 15:41:07 -080017package org.onosproject.incubator.net.virtual.impl.provider;
Brian Stankefb61df42016-07-25 11:47:51 -040018
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onosproject.incubator.net.tunnel.TunnelId;
26import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
27import org.onosproject.incubator.net.virtual.NetworkId;
yoonseon6b972c32016-12-06 16:45:03 -080028import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
29import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
30import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Brian Stankefb61df42016-07-25 11:47:51 -040031import org.onosproject.net.ConnectPoint;
32import org.onosproject.net.Link;
33import org.onosproject.net.Path;
34import org.onosproject.net.link.LinkEvent;
35import org.onosproject.net.provider.AbstractProvider;
36import org.onosproject.net.topology.Topology;
37import org.onosproject.net.topology.TopologyCluster;
38import org.onosproject.net.topology.TopologyEvent;
39import org.onosproject.net.topology.TopologyListener;
40import org.onosproject.net.topology.TopologyService;
41import org.slf4j.Logger;
42
43import java.util.HashSet;
44import java.util.Set;
Thomas Vachuskac8187a02016-08-08 11:56:24 -070045import java.util.concurrent.ExecutorService;
Brian Stankefb61df42016-07-25 11:47:51 -040046
Thomas Vachuskac8187a02016-08-08 11:56:24 -070047import static java.util.concurrent.Executors.newSingleThreadExecutor;
48import static org.onlab.util.Tools.groupedThreads;
Brian Stankefb61df42016-07-25 11:47:51 -040049import static org.slf4j.LoggerFactory.getLogger;
50
51/**
52 * Virtual network topology provider.
53 */
54@Component(immediate = true)
55@Service
yoonseon214963b2016-11-21 15:41:07 -080056public class DefaultVirtualNetworkProvider
57 extends AbstractProvider implements VirtualNetworkProvider {
Brian Stankefb61df42016-07-25 11:47:51 -040058
yoonseon214963b2016-11-21 15:41:07 -080059 private final Logger log = getLogger(DefaultVirtualNetworkProvider.class);
Brian Stankefb61df42016-07-25 11:47:51 -040060
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
62 protected VirtualNetworkProviderRegistry providerRegistry;
63
64 private VirtualNetworkProviderService providerService;
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected TopologyService topologyService;
68
69 protected TopologyListener topologyListener = new InternalTopologyListener();
70
Thomas Vachuskac8187a02016-08-08 11:56:24 -070071 private ExecutorService executor;
72
Brian Stankefb61df42016-07-25 11:47:51 -040073 /**
74 * Default constructor.
75 */
yoonseon214963b2016-11-21 15:41:07 -080076 public DefaultVirtualNetworkProvider() {
Brian Stankefb61df42016-07-25 11:47:51 -040077 super(DefaultVirtualLink.PID);
78 }
79
80 @Activate
81 public void activate() {
Thomas Vachuskac8187a02016-08-08 11:56:24 -070082 executor = newSingleThreadExecutor(groupedThreads("onos/vnet", "provider", log));
Brian Stankefb61df42016-07-25 11:47:51 -040083 providerService = providerRegistry.register(this);
84 topologyService.addListener(topologyListener);
Brian Stankefb61df42016-07-25 11:47:51 -040085 log.info("Started");
86 }
87
88 @Deactivate
89 public void deactivate() {
90 topologyService.removeListener(topologyListener);
Thomas Vachuskad13e4a42016-08-08 14:39:51 -070091 executor.shutdownNow();
Thomas Vachuskac8187a02016-08-08 11:56:24 -070092 executor = null;
Brian Stankefb61df42016-07-25 11:47:51 -040093 providerRegistry.unregister(this);
94 providerService = null;
95 log.info("Stopped");
96 }
97
98 @Override
99 public boolean isTraversable(ConnectPoint src, ConnectPoint dst) {
100 final boolean[] foundSrc = new boolean[1];
101 final boolean[] foundDst = new boolean[1];
102 Topology topology = topologyService.currentTopology();
103 Set<Path> paths = topologyService.getPaths(topology, src.deviceId(), dst.deviceId());
104 paths.forEach(path -> {
105 foundDst[0] = false;
106 foundSrc[0] = false;
107 // Traverse the links in each path to determine if both the src and dst connection
108 // point are in the path, if so then this src/dst pair are traversable.
109 path.links().forEach(link -> {
110 if (link.src().equals(src)) {
111 foundSrc[0] = true;
112 }
113 if (link.dst().equals(dst)) {
114 foundDst[0] = true;
115 }
116 });
117 if (foundSrc[0] && foundDst[0]) {
118 return;
119 }
120 });
121 return foundSrc[0] && foundDst[0];
122 }
123
124 @Override
125 public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
126 return null;
127 }
128
129 @Override
130 public void destroyTunnel(NetworkId networkId, TunnelId tunnelId) {
131
132 }
133
134 /**
135 * Returns a set of set of interconnected connect points in the default topology.
136 * The inner set represents the interconnected connect points, and the outerset
137 * represents separate clusters.
138 *
139 * @param topology the default topology
140 * @return set of set of interconnected connect points.
141 */
yoonseon214963b2016-11-21 15:41:07 -0800142 public Set<Set<ConnectPoint>> getConnectPoints(Topology topology) {
Brian Stankefb61df42016-07-25 11:47:51 -0400143 Set<Set<ConnectPoint>> clusters = new HashSet<>();
144 Set<TopologyCluster> topologyClusters = topologyService.getClusters(topology);
145 topologyClusters.forEach(topologyCluster -> {
146 Set<ConnectPoint> connectPointSet = new HashSet<>();
yoonseon214963b2016-11-21 15:41:07 -0800147 Set<Link> clusterLinks =
148 topologyService.getClusterLinks(topology, topologyCluster);
Brian Stankefb61df42016-07-25 11:47:51 -0400149 clusterLinks.forEach(link -> {
150 connectPointSet.add(link.src());
151 connectPointSet.add(link.dst());
152 });
153 if (!connectPointSet.isEmpty()) {
154 clusters.add(connectPointSet);
155 }
156 });
157 return clusters;
158 }
159
160 /**
161 * Topology event listener.
162 */
163 private class InternalTopologyListener implements TopologyListener {
164 @Override
165 public void event(TopologyEvent event) {
Thomas Vachuskac8187a02016-08-08 11:56:24 -0700166 // Perform processing off the listener thread.
yoonseon214963b2016-11-21 15:41:07 -0800167 executor.submit(() -> providerService
168 .topologyChanged(getConnectPoints(event.subject())));
Brian Stankefb61df42016-07-25 11:47:51 -0400169 }
170
171 @Override
172 public boolean isRelevant(TopologyEvent event) {
Thomas Vachuskac8187a02016-08-08 11:56:24 -0700173 return event.type() == TopologyEvent.Type.TOPOLOGY_CHANGED &&
174 event.reasons().stream().anyMatch(reason -> reason instanceof LinkEvent);
Brian Stankefb61df42016-07-25 11:47:51 -0400175 }
176 }
177}