blob: e8da5cb84df7340f3df5113b46ad502af896738a [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
yoonseon94672112017-01-31 13:46:21 -08002 * Copyright 2017-present Open Networking Foundation
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
Harold Huang3fcf7432017-05-16 16:21:08 +080018import com.google.common.collect.ImmutableSet;
Brian Stanke86914282016-05-25 15:36:50 -040019import com.google.common.collect.Maps;
Brian Stanke11f6d532016-07-05 16:17:59 -040020import org.onlab.osgi.DefaultServiceDirectory;
yoonseonc6a69272017-01-12 18:22:20 -080021import org.onlab.osgi.ServiceDirectory;
Brian Stanke7a81b532016-06-14 15:43:51 -040022import org.onlab.packet.IpAddress;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.VlanId;
yoonseon322c9c32016-12-07 16:47:02 -080025import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070027import org.onosproject.incubator.net.tunnel.TunnelId;
Brian Stankefb61df42016-07-25 11:47:51 -040028import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070029import org.onosproject.incubator.net.virtual.NetworkId;
30import org.onosproject.incubator.net.virtual.TenantId;
31import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040032import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070033import org.onosproject.incubator.net.virtual.VirtualLink;
34import org.onosproject.incubator.net.virtual.VirtualNetwork;
35import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
36import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
37import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
38import org.onosproject.incubator.net.virtual.VirtualNetworkService;
39import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
40import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
41import org.onosproject.incubator.net.virtual.VirtualPort;
yoonseon214963b2016-11-21 15:41:07 -080042import org.onosproject.incubator.net.virtual.VnetService;
Claudine Chiu465a2602017-03-17 18:33:36 -040043import org.onosproject.incubator.net.virtual.event.VirtualEvent;
44import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
yoonseon6b972c32016-12-06 16:45:03 -080045import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
46import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
47import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Harold Huang222c6ec2017-06-02 15:02:49 +080048import org.onosproject.mastership.MastershipAdminService;
Yoonseon Hana578d762017-05-08 13:42:02 -070049import org.onosproject.mastership.MastershipService;
Harold Huang222c6ec2017-06-02 15:02:49 +080050import org.onosproject.mastership.MastershipTermService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070051import org.onosproject.net.ConnectPoint;
52import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040053import org.onosproject.net.HostId;
54import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040055import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070056import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040057import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050058import org.onosproject.net.flow.FlowRuleService;
yoonseon86bebed2017-02-03 15:23:57 -080059import org.onosproject.net.flowobjective.FlowObjectiveService;
Claudine Chiu465a2602017-03-17 18:33:36 -040060import org.onosproject.net.group.GroupService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040061import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040062import org.onosproject.net.intent.IntentService;
Brian Stanke86914282016-05-25 15:36:50 -040063import org.onosproject.net.link.LinkService;
yoonseon94672112017-01-31 13:46:21 -080064import org.onosproject.net.meter.MeterService;
yoonseon322c9c32016-12-07 16:47:02 -080065import org.onosproject.net.packet.PacketService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070066import org.onosproject.net.provider.AbstractListenerProviderRegistry;
67import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000068import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040069import org.onosproject.net.topology.TopologyService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070070import org.osgi.service.component.annotations.Activate;
71import org.osgi.service.component.annotations.Component;
72import org.osgi.service.component.annotations.Deactivate;
73import org.osgi.service.component.annotations.Reference;
74import org.osgi.service.component.annotations.ReferenceCardinality;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070075import org.slf4j.Logger;
76import org.slf4j.LoggerFactory;
77
Harold Huang3fcf7432017-05-16 16:21:08 +080078import java.util.HashSet;
Brian Stanke86914282016-05-25 15:36:50 -040079import java.util.Map;
Claudine Chiue7f6b912017-02-24 14:13:30 -050080import java.util.Objects;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070081import java.util.Set;
82
83import static com.google.common.base.Preconditions.checkNotNull;
84
85/**
86 * Implementation of the virtual network service.
87 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070088@Component(service = {
89 VirtualNetworkService.class,
90 VirtualNetworkAdminService.class,
91 VirtualNetworkService.class,
92 VirtualNetworkProviderRegistry.class
93 })
Thomas Vachuska33979fd2015-07-31 11:41:14 -070094public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080095 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
96 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
Ray Milkeyd84f89b2018-08-17 14:54:17 -070097 implements VirtualNetworkService, VirtualNetworkAdminService, VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070098
99 private final Logger log = LoggerFactory.getLogger(getClass());
100
101 private static final String TENANT_NULL = "Tenant ID cannot be null";
102 private static final String NETWORK_NULL = "Network ID cannot be null";
103 private static final String DEVICE_NULL = "Device ID cannot be null";
104 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
105
yoonseon322c9c32016-12-07 16:47:02 -0800106 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
107 "org.onosproject.virtual-network";
108
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700109 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700110 protected VirtualNetworkStore store;
111
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700112 @Reference(cardinality = ReferenceCardinality.MANDATORY)
yoonseon322c9c32016-12-07 16:47:02 -0800113 protected CoreService coreService;
114
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500115 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700116
yoonseonc6a69272017-01-12 18:22:20 -0800117 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
yoonseon322c9c32016-12-07 16:47:02 -0800118 private ApplicationId appId;
yoonseonc6a69272017-01-12 18:22:20 -0800119
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700120 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700121
Brian Stanke11f6d532016-07-05 16:17:59 -0400122 /**
123 * Only used for Junit test methods outside of this package.
124 *
125 * @param store virtual network store
126 */
127 public void setStore(VirtualNetworkStore store) {
128 this.store = store;
129 }
130
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700131 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400132 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500133 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Claudine Chiu465a2602017-03-17 18:33:36 -0400134 eventDispatcher.addSink(VirtualEvent.class,
135 VirtualListenerRegistryManager.getInstance());
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900136 store.setDelegate(delegate);
yoonseon322c9c32016-12-07 16:47:02 -0800137 appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700138 log.info("Started");
139 }
140
141 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400142 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700143 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500144 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Claudine Chiu465a2602017-03-17 18:33:36 -0400145 eventDispatcher.removeSink(VirtualEvent.class);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700146 log.info("Stopped");
147 }
148
149 @Override
150 public void registerTenantId(TenantId tenantId) {
151 checkNotNull(tenantId, TENANT_NULL);
152 store.addTenantId(tenantId);
153 }
154
155 @Override
156 public void unregisterTenantId(TenantId tenantId) {
157 checkNotNull(tenantId, TENANT_NULL);
158 store.removeTenantId(tenantId);
159 }
160
161 @Override
162 public Set<TenantId> getTenantIds() {
163 return store.getTenantIds();
164 }
165
166 @Override
167 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
168 checkNotNull(tenantId, TENANT_NULL);
169 return store.addNetwork(tenantId);
170 }
171
172 @Override
173 public void removeVirtualNetwork(NetworkId networkId) {
174 checkNotNull(networkId, NETWORK_NULL);
175 store.removeNetwork(networkId);
176 }
177
178 @Override
179 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
180 checkNotNull(networkId, NETWORK_NULL);
181 checkNotNull(deviceId, DEVICE_NULL);
182 return store.addDevice(networkId, deviceId);
183 }
184
185 @Override
186 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
187 checkNotNull(networkId, NETWORK_NULL);
188 checkNotNull(deviceId, DEVICE_NULL);
189 store.removeDevice(networkId, deviceId);
190 }
191
192 @Override
yoonseon214963b2016-11-21 15:41:07 -0800193 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
194 MacAddress mac, VlanId vlan,
195 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400196 checkNotNull(networkId, NETWORK_NULL);
197 checkNotNull(hostId, DEVICE_NULL);
198 return store.addHost(networkId, hostId, mac, vlan, location, ips);
199 }
200
201 @Override
202 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
203 checkNotNull(networkId, NETWORK_NULL);
204 checkNotNull(hostId, DEVICE_NULL);
205 store.removeHost(networkId, hostId);
206 }
207
208 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700209 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400210 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700211 checkNotNull(networkId, NETWORK_NULL);
212 checkNotNull(src, LINK_POINT_NULL);
213 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400214 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
215 checkNotNull(physicalSrc, LINK_POINT_NULL);
216 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
217 checkNotNull(physicalDst, LINK_POINT_NULL);
218
219 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
220 Link.State state = Link.State.INACTIVE;
221 if (provider != null) {
222 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
223 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
224 }
225 return store.addLink(networkId, src, dst, state, null);
226 }
227
228 /**
229 * Maps the virtual connect point to a physical connect point.
230 *
231 * @param networkId network identifier
232 * @param virtualCp virtual connect point
233 * @return physical connect point
234 */
235 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
236 ConnectPoint virtualCp) {
237 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
238 for (VirtualPort port : ports) {
239 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700240 return new ConnectPoint(port.realizedBy().deviceId(),
241 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400242 }
243 }
244 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700245 }
246
Brian Stanke612cebf2016-05-02 10:21:33 -0400247 /**
248 * Maps the physical connect point to a virtual connect point.
249 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400250 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400251 * @param physicalCp physical connect point
252 * @return virtual connect point
253 */
254 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400255 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400256 Set<VirtualPort> ports = store.getPorts(networkId, null);
257 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700258 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
259 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400260 return new ConnectPoint(port.element().id(), port.number());
261 }
262 }
263 return null;
264 }
265
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700266 @Override
yoonseon214963b2016-11-21 15:41:07 -0800267 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
268 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700269 checkNotNull(networkId, NETWORK_NULL);
270 checkNotNull(src, LINK_POINT_NULL);
271 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400272 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700273 }
274
275 @Override
276 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700277 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700278 checkNotNull(networkId, NETWORK_NULL);
279 checkNotNull(deviceId, DEVICE_NULL);
280 checkNotNull(portNumber, "Port description cannot be null");
281 return store.addPort(networkId, deviceId, portNumber, realizedBy);
282 }
283
284 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700285 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
286 PortNumber portNumber, ConnectPoint realizedBy) {
287 checkNotNull(networkId, NETWORK_NULL);
288 checkNotNull(deviceId, DEVICE_NULL);
289 checkNotNull(portNumber, "Port description cannot be null");
290 checkNotNull(realizedBy, "Physical port description cannot be null");
291
292 store.bindPort(networkId, deviceId, portNumber, realizedBy);
293 }
294
295 @Override
Claudine Chiu579969d2017-10-06 14:32:18 -0400296 public void updatePortState(NetworkId networkId, DeviceId deviceId,
297 PortNumber portNumber, boolean isEnabled) {
298 checkNotNull(networkId, NETWORK_NULL);
299 checkNotNull(deviceId, DEVICE_NULL);
300 checkNotNull(portNumber, "Port description cannot be null");
301
302 store.updatePortState(networkId, deviceId, portNumber, isEnabled);
303 }
304
305 @Override
yoonseon214963b2016-11-21 15:41:07 -0800306 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
307 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700308 checkNotNull(networkId, NETWORK_NULL);
309 checkNotNull(deviceId, DEVICE_NULL);
310 checkNotNull(portNumber, "Port number cannot be null");
311 store.removePort(networkId, deviceId, portNumber);
312 }
313
314 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800315 public ServiceDirectory getServiceDirectory() {
316 return serviceDirectory;
317 }
318
319 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700320 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
321 checkNotNull(tenantId, TENANT_NULL);
322 return store.getNetworks(tenantId);
323 }
324
Jovana Vuletac884b692017-11-28 16:52:35 +0100325 @Override
326 public VirtualNetwork getVirtualNetwork(NetworkId networkId) {
Brian Stanke86914282016-05-25 15:36:50 -0400327 checkNotNull(networkId, NETWORK_NULL);
328 return store.getNetwork(networkId);
329 }
330
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700331 @Override
Jovana Vuletac884b692017-11-28 16:52:35 +0100332 public TenantId getTenantId(NetworkId networkId) {
333 VirtualNetwork virtualNetwork = getVirtualNetwork(networkId);
334 checkNotNull(virtualNetwork, "The network does not exist.");
335 return virtualNetwork.tenantId();
336 }
337
338 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700339 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
340 checkNotNull(networkId, NETWORK_NULL);
341 return store.getDevices(networkId);
342 }
343
344 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400345 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
346 checkNotNull(networkId, NETWORK_NULL);
347 return store.getHosts(networkId);
348 }
349
350 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700351 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
352 checkNotNull(networkId, NETWORK_NULL);
353 return store.getLinks(networkId);
354 }
355
356 @Override
357 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
358 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700359 return store.getPorts(networkId, deviceId);
360 }
361
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700362 @Override
Harold Huang3fcf7432017-05-16 16:21:08 +0800363 public Set<DeviceId> getPhysicalDevices(NetworkId networkId, DeviceId deviceId) {
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700364 checkNotNull(networkId, "Network ID cannot be null");
Harold Huang3fcf7432017-05-16 16:21:08 +0800365 checkNotNull(deviceId, "Virtual device ID cannot be null");
366 Set<VirtualPort> virtualPortSet = getVirtualPorts(networkId, deviceId);
367 Set<DeviceId> physicalDeviceSet = new HashSet<>();
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700368
369 virtualPortSet.forEach(virtualPort -> {
370 if (virtualPort.realizedBy() != null) {
371 physicalDeviceSet.add(virtualPort.realizedBy().deviceId());
372 }
373 });
374
Harold Huang3fcf7432017-05-16 16:21:08 +0800375 return ImmutableSet.copyOf(physicalDeviceSet);
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700376 }
377
Brian Stanke86914282016-05-25 15:36:50 -0400378 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
379
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700380 @Override
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900381 @SuppressWarnings("unchecked")
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700382 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
383 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400384 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
385 VnetService service = lookup(serviceKey);
386 if (service == null) {
387 service = create(serviceKey);
388 }
389 return (T) service;
390 }
391
yoonseon322c9c32016-12-07 16:47:02 -0800392 @Override
393 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
394 return appId;
395 }
396
Brian Stanke11f6d532016-07-05 16:17:59 -0400397 /**
398 * Returns the Vnet service matching the service key.
399 *
400 * @param serviceKey service key
401 * @return vnet service
402 */
Brian Stanke86914282016-05-25 15:36:50 -0400403 private VnetService lookup(ServiceKey serviceKey) {
404 return networkServices.get(serviceKey);
405 }
406
Brian Stanke11f6d532016-07-05 16:17:59 -0400407 /**
408 * Creates a new service key using the specified network identifier and service class.
409 *
410 * @param networkId network identifier
411 * @param serviceClass service class
412 * @param <T> type of service
413 * @return service key
414 */
Brian Stanke86914282016-05-25 15:36:50 -0400415 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
416 return new ServiceKey(networkId, serviceClass);
417 }
418
419
Brian Stanke11f6d532016-07-05 16:17:59 -0400420 /**
421 * Create a new vnet service instance.
422 *
423 * @param serviceKey service key
424 * @return vnet service
425 */
Brian Stanke86914282016-05-25 15:36:50 -0400426 private VnetService create(ServiceKey serviceKey) {
427 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400428 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800429
Brian Stanke86914282016-05-25 15:36:50 -0400430 VnetService service;
431 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800432 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400433 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800434 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400435 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800436 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400437 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800438 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400439 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800440 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000441 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800442 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500443 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800444 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800445 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
446 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800447 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
448 service = new VirtualNetworkGroupManager(this, network.id());
yoonseon94672112017-01-31 13:46:21 -0800449 } else if (serviceKey.serviceClass.equals(MeterService.class)) {
450 service = new VirtualNetworkMeterManager(this, network.id());
yoonseon86bebed2017-02-03 15:23:57 -0800451 } else if (serviceKey.serviceClass.equals(FlowObjectiveService.class)) {
452 service = new VirtualNetworkFlowObjectiveManager(this, network.id());
Harold Huang222c6ec2017-06-02 15:02:49 +0800453 } else if (serviceKey.serviceClass.equals(MastershipService.class) ||
454 serviceKey.serviceClass.equals(MastershipAdminService.class) ||
455 serviceKey.serviceClass.equals(MastershipTermService.class)) {
Yoonseon Hana578d762017-05-08 13:42:02 -0700456 service = new VirtualNetworkMastershipManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400457 } else {
458 return null;
459 }
460 networkServices.put(serviceKey, service);
461 return service;
462 }
463
Brian Stanke11f6d532016-07-05 16:17:59 -0400464 /**
465 * Service key class.
466 */
Claudine Chiu9a18f492017-02-27 15:57:06 -0500467 private static class ServiceKey {
Brian Stanke86914282016-05-25 15:36:50 -0400468 final NetworkId networkId;
469 final Class serviceClass;
470
Brian Stanke11f6d532016-07-05 16:17:59 -0400471 /**
472 * Constructor for service key.
473 *
474 * @param networkId network identifier
475 * @param serviceClass service class
476 */
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900477 ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800478
Brian Stanke86914282016-05-25 15:36:50 -0400479 checkNotNull(networkId, NETWORK_NULL);
480 this.networkId = networkId;
481 this.serviceClass = serviceClass;
482 }
483
Brian Stanke11f6d532016-07-05 16:17:59 -0400484 /**
485 * Returns the network identifier.
486 *
487 * @return network identifier
488 */
Brian Stanke86914282016-05-25 15:36:50 -0400489 public NetworkId networkId() {
490 return networkId;
491 }
492
Brian Stanke11f6d532016-07-05 16:17:59 -0400493 /**
494 * Returns the service class.
495 *
496 * @return service class
497 */
Brian Stanke86914282016-05-25 15:36:50 -0400498 public Class serviceClass() {
499 return serviceClass;
500 }
Claudine Chiue7f6b912017-02-24 14:13:30 -0500501
502 @Override
503 public int hashCode() {
504 return Objects.hash(networkId, serviceClass);
505 }
506
507 @Override
508 public boolean equals(Object obj) {
509 if (this == obj) {
510 return true;
511 }
512 if (obj instanceof ServiceKey) {
513 ServiceKey that = (ServiceKey) obj;
514 return Objects.equals(this.networkId, that.networkId) &&
515 Objects.equals(this.serviceClass, that.serviceClass);
516 }
517 return false;
518 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700519 }
520
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700521 @Override
yoonseon214963b2016-11-21 15:41:07 -0800522 protected VirtualNetworkProviderService
523 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700524 return new InternalVirtualNetworkProviderService(provider);
525 }
526
Brian Stankefb61df42016-07-25 11:47:51 -0400527 /**
528 * Service issued to registered virtual network providers so that they
529 * can interact with the core.
530 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700531 private class InternalVirtualNetworkProviderService
532 extends AbstractProviderService<VirtualNetworkProvider>
533 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400534 /**
535 * Constructor.
536 * @param provider virtual network provider
537 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700538 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
539 super(provider);
540 }
Brian Stanke4d579882016-04-22 13:28:46 -0400541
542 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400543 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400544 Set<TenantId> tenantIds = getTenantIds();
545 tenantIds.forEach(tenantId -> {
546 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
547
548 virtualNetworks.forEach(virtualNetwork -> {
549 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
550
551 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800552 if (isVirtualLinkInCluster(virtualNetwork.id(),
553 virtualLink, clusters)) {
554 store.updateLink(virtualLink, virtualLink.tunnelId(),
555 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400556 } else {
yoonseon214963b2016-11-21 15:41:07 -0800557 store.updateLink(virtualLink, virtualLink.tunnelId(),
558 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400559 }
560 });
561 });
562 });
563 }
564
565 /**
yoonseon214963b2016-11-21 15:41:07 -0800566 * Determines if the virtual link (both source and destination connect point)
567 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400568 *
569 * @param networkId virtual network identifier
570 * @param virtualLink virtual link
571 * @param clusters topology clusters
572 * @return true if the virtual link is in a cluster.
573 */
574 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
575 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800576 ConnectPoint srcPhysicalCp =
577 mapVirtualToPhysicalPort(networkId, virtualLink.src());
578 ConnectPoint dstPhysicalCp =
579 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400580
581 final boolean[] foundSrc = {false};
582 final boolean[] foundDst = {false};
583 clusters.forEach(connectPoints -> {
584 connectPoints.forEach(connectPoint -> {
585 if (connectPoint.equals(srcPhysicalCp)) {
586 foundSrc[0] = true;
587 } else if (connectPoint.equals(dstPhysicalCp)) {
588 foundDst[0] = true;
589 }
590 });
591 if (foundSrc[0] && foundDst[0]) {
592 return;
593 }
594 });
595 return foundSrc[0] && foundDst[0];
596 }
597
598 @Override
yoonseon214963b2016-11-21 15:41:07 -0800599 public void tunnelUp(NetworkId networkId, ConnectPoint src,
600 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400601 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
602 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
603 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
604 log.error("Src or dst virtual connection point was not found.");
605 }
606
607 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
608 if (virtualLink != null) {
609 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
610 }
Brian Stanke4d579882016-04-22 13:28:46 -0400611 }
612
613 @Override
yoonseon214963b2016-11-21 15:41:07 -0800614 public void tunnelDown(NetworkId networkId, ConnectPoint src,
615 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400616 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
617 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
618 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
619 log.error("Src or dst virtual connection point was not found.");
620 }
Brian Stanke4d579882016-04-22 13:28:46 -0400621
Brian Stanke612cebf2016-05-02 10:21:33 -0400622 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
623 if (virtualLink != null) {
624 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
625 }
Brian Stanke4d579882016-04-22 13:28:46 -0400626 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700627 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700628}