blob: 4ac01177ff97847d07db10d016b7b0816ccd92a9 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska33979fd2015-07-31 11:41:14 -07003 *
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.incubator.net.virtual.impl;
17
Brian Stanke86914282016-05-25 15:36:50 -040018import com.google.common.collect.Maps;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070019import 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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070025import org.onosproject.incubator.net.tunnel.TunnelId;
26import org.onosproject.incubator.net.virtual.NetworkId;
27import org.onosproject.incubator.net.virtual.TenantId;
28import org.onosproject.incubator.net.virtual.VirtualDevice;
29import org.onosproject.incubator.net.virtual.VirtualLink;
30import org.onosproject.incubator.net.virtual.VirtualNetwork;
31import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
32import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
33import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070034import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
35import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
36import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070037import org.onosproject.incubator.net.virtual.VirtualNetworkService;
38import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
39import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
40import org.onosproject.incubator.net.virtual.VirtualPort;
41import org.onosproject.net.ConnectPoint;
42import org.onosproject.net.DeviceId;
Brian Stanke612cebf2016-05-02 10:21:33 -040043import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070044import org.onosproject.net.Port;
45import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040046import org.onosproject.net.device.DeviceService;
47import org.onosproject.net.link.LinkService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070048import org.onosproject.net.provider.AbstractListenerProviderRegistry;
49import org.onosproject.net.provider.AbstractProviderService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040050import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070051import org.slf4j.Logger;
52import org.slf4j.LoggerFactory;
53
Brian Stanke86914282016-05-25 15:36:50 -040054import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070055import java.util.Set;
56
57import static com.google.common.base.Preconditions.checkNotNull;
58
59/**
60 * Implementation of the virtual network service.
61 */
62@Component(immediate = true)
63@Service
64public class VirtualNetworkManager
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070065 extends AbstractListenerProviderRegistry<VirtualNetworkEvent, VirtualNetworkListener,
Brian Stanke0e5c94e2016-03-08 11:20:04 -050066 VirtualNetworkProvider, VirtualNetworkProviderService>
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070067 implements VirtualNetworkService, VirtualNetworkAdminService, VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070068
69 private final Logger log = LoggerFactory.getLogger(getClass());
70
71 private static final String TENANT_NULL = "Tenant ID cannot be null";
72 private static final String NETWORK_NULL = "Network ID cannot be null";
73 private static final String DEVICE_NULL = "Device ID cannot be null";
74 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
Brian Stanke9a108972016-04-11 15:25:17 -040075 private static final String VIRTUAL_LINK_NULL = "Virtual Link cannot be null";
Thomas Vachuska33979fd2015-07-31 11:41:14 -070076
77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 protected VirtualNetworkStore store;
79
Brian Stanke0e5c94e2016-03-08 11:20:04 -050080 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070081
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070082 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -070083
84 @Activate
85 protected void activate() {
86 store.setDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -050087 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
88
Thomas Vachuska33979fd2015-07-31 11:41:14 -070089 log.info("Started");
90 }
91
92 @Deactivate
93 protected void deactivate() {
94 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -050095 eventDispatcher.removeSink(VirtualNetworkEvent.class);
96
Thomas Vachuska33979fd2015-07-31 11:41:14 -070097 log.info("Stopped");
98 }
99
100 @Override
101 public void registerTenantId(TenantId tenantId) {
102 checkNotNull(tenantId, TENANT_NULL);
103 store.addTenantId(tenantId);
104 }
105
106 @Override
107 public void unregisterTenantId(TenantId tenantId) {
108 checkNotNull(tenantId, TENANT_NULL);
109 store.removeTenantId(tenantId);
110 }
111
112 @Override
113 public Set<TenantId> getTenantIds() {
114 return store.getTenantIds();
115 }
116
117 @Override
118 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
119 checkNotNull(tenantId, TENANT_NULL);
120 return store.addNetwork(tenantId);
121 }
122
123 @Override
124 public void removeVirtualNetwork(NetworkId networkId) {
125 checkNotNull(networkId, NETWORK_NULL);
126 store.removeNetwork(networkId);
127 }
128
129 @Override
130 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
131 checkNotNull(networkId, NETWORK_NULL);
132 checkNotNull(deviceId, DEVICE_NULL);
133 return store.addDevice(networkId, deviceId);
134 }
135
136 @Override
137 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
138 checkNotNull(networkId, NETWORK_NULL);
139 checkNotNull(deviceId, DEVICE_NULL);
140 store.removeDevice(networkId, deviceId);
141 }
142
143 @Override
144 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400145 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700146 checkNotNull(networkId, NETWORK_NULL);
147 checkNotNull(src, LINK_POINT_NULL);
148 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke612cebf2016-05-02 10:21:33 -0400149 VirtualLink virtualLink = store.addLink(networkId, src, dst, Link.State.INACTIVE, null);
Brian Stanke9a108972016-04-11 15:25:17 -0400150 checkNotNull(virtualLink, VIRTUAL_LINK_NULL);
151
152 if (virtualLink.providerId() != null) {
153 VirtualNetworkProvider provider = getProvider(virtualLink.providerId());
154 if (provider != null) {
155 TunnelId tunnelId = provider.createTunnel(networkId, mapVirtualToPhysicalPort(networkId, src),
156 mapVirtualToPhysicalPort(networkId, dst));
Brian Stanke612cebf2016-05-02 10:21:33 -0400157 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
Brian Stanke9a108972016-04-11 15:25:17 -0400158 }
159 }
160 return virtualLink;
161 }
162
163 /**
164 * Maps the virtual connect point to a physical connect point.
165 *
166 * @param networkId network identifier
167 * @param virtualCp virtual connect point
168 * @return physical connect point
169 */
170 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
171 ConnectPoint virtualCp) {
172 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
173 for (VirtualPort port : ports) {
174 if (port.element().id().equals(virtualCp.elementId()) &&
175 port.number().equals(virtualCp.port())) {
176 return new ConnectPoint(port.realizedBy().element().id(), port.realizedBy().number());
177 }
178 }
179 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700180 }
181
Brian Stanke612cebf2016-05-02 10:21:33 -0400182 /**
183 * Maps the physical connect point to a virtual connect point.
184 *
185 * @param networkId network identifier
186 * @param physicalCp physical connect point
187 * @return virtual connect point
188 */
189 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
190 ConnectPoint physicalCp) {
191 Set<VirtualPort> ports = store.getPorts(networkId, null);
192 for (VirtualPort port : ports) {
193 if (port.realizedBy().element().id().equals(physicalCp.elementId()) &&
194 port.realizedBy().number().equals(physicalCp.port())) {
195 return new ConnectPoint(port.element().id(), port.number());
196 }
197 }
198 return null;
199 }
200
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700201 @Override
202 public void removeVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
203 checkNotNull(networkId, NETWORK_NULL);
204 checkNotNull(src, LINK_POINT_NULL);
205 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke9a108972016-04-11 15:25:17 -0400206 VirtualLink virtualLink = store.removeLink(networkId, src, dst);
207
208 if (virtualLink != null && virtualLink.providerId() != null) {
209 VirtualNetworkProvider provider = getProvider(virtualLink.providerId());
210 if (provider != null) {
211 provider.destroyTunnel(networkId, virtualLink.tunnelId());
212 }
213 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700214 }
215
216 @Override
217 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
218 PortNumber portNumber, Port realizedBy) {
219 checkNotNull(networkId, NETWORK_NULL);
220 checkNotNull(deviceId, DEVICE_NULL);
221 checkNotNull(portNumber, "Port description cannot be null");
222 return store.addPort(networkId, deviceId, portNumber, realizedBy);
223 }
224
225 @Override
226 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
227 checkNotNull(networkId, NETWORK_NULL);
228 checkNotNull(deviceId, DEVICE_NULL);
229 checkNotNull(portNumber, "Port number cannot be null");
230 store.removePort(networkId, deviceId, portNumber);
231 }
232
233 @Override
234 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
235 checkNotNull(tenantId, TENANT_NULL);
236 return store.getNetworks(tenantId);
237 }
238
Brian Stanke86914282016-05-25 15:36:50 -0400239 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
240 checkNotNull(networkId, NETWORK_NULL);
241 return store.getNetwork(networkId);
242 }
243
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700244 @Override
245 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
246 checkNotNull(networkId, NETWORK_NULL);
247 return store.getDevices(networkId);
248 }
249
250 @Override
251 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
252 checkNotNull(networkId, NETWORK_NULL);
253 return store.getLinks(networkId);
254 }
255
256 @Override
257 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
258 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700259 return store.getPorts(networkId, deviceId);
260 }
261
Brian Stanke86914282016-05-25 15:36:50 -0400262 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
263
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700264 @Override
265 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
266 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400267 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
268 VnetService service = lookup(serviceKey);
269 if (service == null) {
270 service = create(serviceKey);
271 }
272 return (T) service;
273 }
274
275 private VnetService lookup(ServiceKey serviceKey) {
276 return networkServices.get(serviceKey);
277 }
278
279 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
280 return new ServiceKey(networkId, serviceClass);
281 }
282
283
284 private VnetService create(ServiceKey serviceKey) {
285 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
286 VnetService service;
287 if (serviceKey.serviceClass.equals(DeviceService.class)) {
288 service = new VirtualNetworkDeviceService(this, network);
289 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
290 service = new VirtualNetworkLinkService(this, network);
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400291 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
292 service = new VirtualNetworkTopologyService(this, network);
Brian Stanke86914282016-05-25 15:36:50 -0400293 } else {
294 return null;
295 }
296 networkServices.put(serviceKey, service);
297 return service;
298 }
299
300 private class ServiceKey {
301 final NetworkId networkId;
302 final Class serviceClass;
303
304 public ServiceKey(NetworkId networkId, Class serviceClass) {
305 checkNotNull(networkId, NETWORK_NULL);
306 this.networkId = networkId;
307 this.serviceClass = serviceClass;
308 }
309
310 public NetworkId networkId() {
311 return networkId;
312 }
313
314 public Class serviceClass() {
315 return serviceClass;
316 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700317 }
318
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700319 @Override
320 protected VirtualNetworkProviderService createProviderService(VirtualNetworkProvider provider) {
321 return new InternalVirtualNetworkProviderService(provider);
322 }
323
324 // Service issued to registered virtual network providers so that they
325 // can interact with the core.
326 private class InternalVirtualNetworkProviderService
327 extends AbstractProviderService<VirtualNetworkProvider>
328 implements VirtualNetworkProviderService {
329 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
330 super(provider);
331 }
Brian Stanke4d579882016-04-22 13:28:46 -0400332
333 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400334 public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke4d579882016-04-22 13:28:46 -0400335
Brian Stanke612cebf2016-05-02 10:21:33 -0400336 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
337 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
338 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
339 log.error("Src or dst virtual connection point was not found.");
340 }
341
342 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
343 if (virtualLink != null) {
344 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
345 }
Brian Stanke4d579882016-04-22 13:28:46 -0400346 }
347
348 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400349 public void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
350 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
351 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
352 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
353 log.error("Src or dst virtual connection point was not found.");
354 }
Brian Stanke4d579882016-04-22 13:28:46 -0400355
Brian Stanke612cebf2016-05-02 10:21:33 -0400356 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
357 if (virtualLink != null) {
358 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
359 }
Brian Stanke4d579882016-04-22 13:28:46 -0400360 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700361 }
362
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700363}