blob: 2343b3eb947ece62e5b7b04458aa7af526ae3d39 [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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
Brian Stanke11f6d532016-07-05 16:17:59 -040026import org.onlab.osgi.DefaultServiceDirectory;
yoonseonc6a69272017-01-12 18:22:20 -080027import org.onlab.osgi.ServiceDirectory;
Brian Stanke7a81b532016-06-14 15:43:51 -040028import org.onlab.packet.IpAddress;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
yoonseon322c9c32016-12-07 16:47:02 -080031import org.onosproject.core.ApplicationId;
32import org.onosproject.core.CoreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070033import org.onosproject.incubator.net.tunnel.TunnelId;
Brian Stankefb61df42016-07-25 11:47:51 -040034import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070035import org.onosproject.incubator.net.virtual.NetworkId;
36import org.onosproject.incubator.net.virtual.TenantId;
37import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040038import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070039import org.onosproject.incubator.net.virtual.VirtualLink;
40import org.onosproject.incubator.net.virtual.VirtualNetwork;
41import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
42import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
43import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
44import org.onosproject.incubator.net.virtual.VirtualNetworkService;
45import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
46import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
47import org.onosproject.incubator.net.virtual.VirtualPort;
yoonseon214963b2016-11-21 15:41:07 -080048import org.onosproject.incubator.net.virtual.VnetService;
Claudine Chiu465a2602017-03-17 18:33:36 -040049import org.onosproject.incubator.net.virtual.event.VirtualEvent;
50import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
yoonseon6b972c32016-12-06 16:45:03 -080051import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
52import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
53import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Harold Huang222c6ec2017-06-02 15:02:49 +080054import org.onosproject.mastership.MastershipAdminService;
Yoonseon Hana578d762017-05-08 13:42:02 -070055import org.onosproject.mastership.MastershipService;
Harold Huang222c6ec2017-06-02 15:02:49 +080056import org.onosproject.mastership.MastershipTermService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070057import org.onosproject.net.ConnectPoint;
58import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040059import org.onosproject.net.HostId;
60import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040061import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070062import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040063import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050064import org.onosproject.net.flow.FlowRuleService;
yoonseon86bebed2017-02-03 15:23:57 -080065import org.onosproject.net.flowobjective.FlowObjectiveService;
Claudine Chiu465a2602017-03-17 18:33:36 -040066import org.onosproject.net.group.GroupService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040067import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040068import org.onosproject.net.intent.IntentService;
Brian Stanke86914282016-05-25 15:36:50 -040069import org.onosproject.net.link.LinkService;
yoonseon94672112017-01-31 13:46:21 -080070import org.onosproject.net.meter.MeterService;
yoonseon322c9c32016-12-07 16:47:02 -080071import org.onosproject.net.packet.PacketService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070072import org.onosproject.net.provider.AbstractListenerProviderRegistry;
73import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000074import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040075import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070076import org.slf4j.Logger;
77import org.slf4j.LoggerFactory;
78
Harold Huang3fcf7432017-05-16 16:21:08 +080079import java.util.HashSet;
Brian Stanke86914282016-05-25 15:36:50 -040080import java.util.Map;
Claudine Chiue7f6b912017-02-24 14:13:30 -050081import java.util.Objects;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070082import java.util.Set;
83
84import static com.google.common.base.Preconditions.checkNotNull;
85
86/**
87 * Implementation of the virtual network service.
88 */
89@Component(immediate = true)
90@Service
91public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080092 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
93 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
94 implements VirtualNetworkService, VirtualNetworkAdminService,
95 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070096
97 private final Logger log = LoggerFactory.getLogger(getClass());
98
99 private static final String TENANT_NULL = "Tenant ID cannot be null";
100 private static final String NETWORK_NULL = "Network ID cannot be null";
101 private static final String DEVICE_NULL = "Device ID cannot be null";
102 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
103
yoonseon322c9c32016-12-07 16:47:02 -0800104 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
105 "org.onosproject.virtual-network";
106
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected VirtualNetworkStore store;
109
Brian Stanke11f6d532016-07-05 16:17:59 -0400110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
yoonseon322c9c32016-12-07 16:47:02 -0800111 protected CoreService coreService;
112
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500113 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700114
yoonseonc6a69272017-01-12 18:22:20 -0800115 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
yoonseon322c9c32016-12-07 16:47:02 -0800116 private ApplicationId appId;
yoonseonc6a69272017-01-12 18:22:20 -0800117
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700118 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700119
Brian Stanke11f6d532016-07-05 16:17:59 -0400120 /**
121 * Only used for Junit test methods outside of this package.
122 *
123 * @param store virtual network store
124 */
125 public void setStore(VirtualNetworkStore store) {
126 this.store = store;
127 }
128
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700129 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400130 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500131 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Claudine Chiu465a2602017-03-17 18:33:36 -0400132 eventDispatcher.addSink(VirtualEvent.class,
133 VirtualListenerRegistryManager.getInstance());
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900134 store.setDelegate(delegate);
yoonseon322c9c32016-12-07 16:47:02 -0800135 appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700136 log.info("Started");
137 }
138
139 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400140 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700141 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500142 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Claudine Chiu465a2602017-03-17 18:33:36 -0400143 eventDispatcher.removeSink(VirtualEvent.class);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700144 log.info("Stopped");
145 }
146
147 @Override
148 public void registerTenantId(TenantId tenantId) {
149 checkNotNull(tenantId, TENANT_NULL);
150 store.addTenantId(tenantId);
151 }
152
153 @Override
154 public void unregisterTenantId(TenantId tenantId) {
155 checkNotNull(tenantId, TENANT_NULL);
156 store.removeTenantId(tenantId);
157 }
158
159 @Override
160 public Set<TenantId> getTenantIds() {
161 return store.getTenantIds();
162 }
163
164 @Override
165 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
166 checkNotNull(tenantId, TENANT_NULL);
167 return store.addNetwork(tenantId);
168 }
169
170 @Override
171 public void removeVirtualNetwork(NetworkId networkId) {
172 checkNotNull(networkId, NETWORK_NULL);
173 store.removeNetwork(networkId);
174 }
175
176 @Override
177 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
178 checkNotNull(networkId, NETWORK_NULL);
179 checkNotNull(deviceId, DEVICE_NULL);
180 return store.addDevice(networkId, deviceId);
181 }
182
183 @Override
184 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
185 checkNotNull(networkId, NETWORK_NULL);
186 checkNotNull(deviceId, DEVICE_NULL);
187 store.removeDevice(networkId, deviceId);
188 }
189
190 @Override
yoonseon214963b2016-11-21 15:41:07 -0800191 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
192 MacAddress mac, VlanId vlan,
193 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400194 checkNotNull(networkId, NETWORK_NULL);
195 checkNotNull(hostId, DEVICE_NULL);
196 return store.addHost(networkId, hostId, mac, vlan, location, ips);
197 }
198
199 @Override
200 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
201 checkNotNull(networkId, NETWORK_NULL);
202 checkNotNull(hostId, DEVICE_NULL);
203 store.removeHost(networkId, hostId);
204 }
205
206 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700207 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400208 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700209 checkNotNull(networkId, NETWORK_NULL);
210 checkNotNull(src, LINK_POINT_NULL);
211 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400212 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
213 checkNotNull(physicalSrc, LINK_POINT_NULL);
214 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
215 checkNotNull(physicalDst, LINK_POINT_NULL);
216
217 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
218 Link.State state = Link.State.INACTIVE;
219 if (provider != null) {
220 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
221 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
222 }
223 return store.addLink(networkId, src, dst, state, null);
224 }
225
226 /**
227 * Maps the virtual connect point to a physical connect point.
228 *
229 * @param networkId network identifier
230 * @param virtualCp virtual connect point
231 * @return physical connect point
232 */
233 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
234 ConnectPoint virtualCp) {
235 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
236 for (VirtualPort port : ports) {
237 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700238 return new ConnectPoint(port.realizedBy().deviceId(),
239 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400240 }
241 }
242 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700243 }
244
Brian Stanke612cebf2016-05-02 10:21:33 -0400245 /**
246 * Maps the physical connect point to a virtual connect point.
247 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400248 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400249 * @param physicalCp physical connect point
250 * @return virtual connect point
251 */
252 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400253 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400254 Set<VirtualPort> ports = store.getPorts(networkId, null);
255 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700256 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
257 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400258 return new ConnectPoint(port.element().id(), port.number());
259 }
260 }
261 return null;
262 }
263
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700264 @Override
yoonseon214963b2016-11-21 15:41:07 -0800265 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
266 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700267 checkNotNull(networkId, NETWORK_NULL);
268 checkNotNull(src, LINK_POINT_NULL);
269 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400270 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700271 }
272
273 @Override
274 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700275 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700276 checkNotNull(networkId, NETWORK_NULL);
277 checkNotNull(deviceId, DEVICE_NULL);
278 checkNotNull(portNumber, "Port description cannot be null");
279 return store.addPort(networkId, deviceId, portNumber, realizedBy);
280 }
281
282 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700283 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
284 PortNumber portNumber, ConnectPoint realizedBy) {
285 checkNotNull(networkId, NETWORK_NULL);
286 checkNotNull(deviceId, DEVICE_NULL);
287 checkNotNull(portNumber, "Port description cannot be null");
288 checkNotNull(realizedBy, "Physical port description cannot be null");
289
290 store.bindPort(networkId, deviceId, portNumber, realizedBy);
291 }
292
293 @Override
Claudine Chiu579969d2017-10-06 14:32:18 -0400294 public void updatePortState(NetworkId networkId, DeviceId deviceId,
295 PortNumber portNumber, boolean isEnabled) {
296 checkNotNull(networkId, NETWORK_NULL);
297 checkNotNull(deviceId, DEVICE_NULL);
298 checkNotNull(portNumber, "Port description cannot be null");
299
300 store.updatePortState(networkId, deviceId, portNumber, isEnabled);
301 }
302
303 @Override
yoonseon214963b2016-11-21 15:41:07 -0800304 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
305 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700306 checkNotNull(networkId, NETWORK_NULL);
307 checkNotNull(deviceId, DEVICE_NULL);
308 checkNotNull(portNumber, "Port number cannot be null");
309 store.removePort(networkId, deviceId, portNumber);
310 }
311
312 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800313 public ServiceDirectory getServiceDirectory() {
314 return serviceDirectory;
315 }
316
317 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700318 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
319 checkNotNull(tenantId, TENANT_NULL);
320 return store.getNetworks(tenantId);
321 }
322
Jovana Vuletac884b692017-11-28 16:52:35 +0100323 @Override
324 public VirtualNetwork getVirtualNetwork(NetworkId networkId) {
Brian Stanke86914282016-05-25 15:36:50 -0400325 checkNotNull(networkId, NETWORK_NULL);
326 return store.getNetwork(networkId);
327 }
328
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700329 @Override
Jovana Vuletac884b692017-11-28 16:52:35 +0100330 public TenantId getTenantId(NetworkId networkId) {
331 VirtualNetwork virtualNetwork = getVirtualNetwork(networkId);
332 checkNotNull(virtualNetwork, "The network does not exist.");
333 return virtualNetwork.tenantId();
334 }
335
336 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700337 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
338 checkNotNull(networkId, NETWORK_NULL);
339 return store.getDevices(networkId);
340 }
341
342 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400343 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
344 checkNotNull(networkId, NETWORK_NULL);
345 return store.getHosts(networkId);
346 }
347
348 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700349 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
350 checkNotNull(networkId, NETWORK_NULL);
351 return store.getLinks(networkId);
352 }
353
354 @Override
355 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
356 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700357 return store.getPorts(networkId, deviceId);
358 }
359
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700360 @Override
Harold Huang3fcf7432017-05-16 16:21:08 +0800361 public Set<DeviceId> getPhysicalDevices(NetworkId networkId, DeviceId deviceId) {
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700362 checkNotNull(networkId, "Network ID cannot be null");
Harold Huang3fcf7432017-05-16 16:21:08 +0800363 checkNotNull(deviceId, "Virtual device ID cannot be null");
364 Set<VirtualPort> virtualPortSet = getVirtualPorts(networkId, deviceId);
365 Set<DeviceId> physicalDeviceSet = new HashSet<>();
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700366
367 virtualPortSet.forEach(virtualPort -> {
368 if (virtualPort.realizedBy() != null) {
369 physicalDeviceSet.add(virtualPort.realizedBy().deviceId());
370 }
371 });
372
Harold Huang3fcf7432017-05-16 16:21:08 +0800373 return ImmutableSet.copyOf(physicalDeviceSet);
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700374 }
375
Brian Stanke86914282016-05-25 15:36:50 -0400376 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
377
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700378 @Override
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900379 @SuppressWarnings("unchecked")
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700380 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
381 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400382 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
383 VnetService service = lookup(serviceKey);
384 if (service == null) {
385 service = create(serviceKey);
386 }
387 return (T) service;
388 }
389
yoonseon322c9c32016-12-07 16:47:02 -0800390 @Override
391 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
392 return appId;
393 }
394
Brian Stanke11f6d532016-07-05 16:17:59 -0400395 /**
396 * Returns the Vnet service matching the service key.
397 *
398 * @param serviceKey service key
399 * @return vnet service
400 */
Brian Stanke86914282016-05-25 15:36:50 -0400401 private VnetService lookup(ServiceKey serviceKey) {
402 return networkServices.get(serviceKey);
403 }
404
Brian Stanke11f6d532016-07-05 16:17:59 -0400405 /**
406 * Creates a new service key using the specified network identifier and service class.
407 *
408 * @param networkId network identifier
409 * @param serviceClass service class
410 * @param <T> type of service
411 * @return service key
412 */
Brian Stanke86914282016-05-25 15:36:50 -0400413 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
414 return new ServiceKey(networkId, serviceClass);
415 }
416
417
Brian Stanke11f6d532016-07-05 16:17:59 -0400418 /**
419 * Create a new vnet service instance.
420 *
421 * @param serviceKey service key
422 * @return vnet service
423 */
Brian Stanke86914282016-05-25 15:36:50 -0400424 private VnetService create(ServiceKey serviceKey) {
425 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400426 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800427
Brian Stanke86914282016-05-25 15:36:50 -0400428 VnetService service;
429 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800430 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400431 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800432 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400433 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800434 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400435 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800436 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400437 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800438 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000439 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800440 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500441 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800442 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800443 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
444 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800445 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
446 service = new VirtualNetworkGroupManager(this, network.id());
yoonseon94672112017-01-31 13:46:21 -0800447 } else if (serviceKey.serviceClass.equals(MeterService.class)) {
448 service = new VirtualNetworkMeterManager(this, network.id());
yoonseon86bebed2017-02-03 15:23:57 -0800449 } else if (serviceKey.serviceClass.equals(FlowObjectiveService.class)) {
450 service = new VirtualNetworkFlowObjectiveManager(this, network.id());
Harold Huang222c6ec2017-06-02 15:02:49 +0800451 } else if (serviceKey.serviceClass.equals(MastershipService.class) ||
452 serviceKey.serviceClass.equals(MastershipAdminService.class) ||
453 serviceKey.serviceClass.equals(MastershipTermService.class)) {
Yoonseon Hana578d762017-05-08 13:42:02 -0700454 service = new VirtualNetworkMastershipManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400455 } else {
456 return null;
457 }
458 networkServices.put(serviceKey, service);
459 return service;
460 }
461
Brian Stanke11f6d532016-07-05 16:17:59 -0400462 /**
463 * Service key class.
464 */
Claudine Chiu9a18f492017-02-27 15:57:06 -0500465 private static class ServiceKey {
Brian Stanke86914282016-05-25 15:36:50 -0400466 final NetworkId networkId;
467 final Class serviceClass;
468
Brian Stanke11f6d532016-07-05 16:17:59 -0400469 /**
470 * Constructor for service key.
471 *
472 * @param networkId network identifier
473 * @param serviceClass service class
474 */
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900475 ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800476
Brian Stanke86914282016-05-25 15:36:50 -0400477 checkNotNull(networkId, NETWORK_NULL);
478 this.networkId = networkId;
479 this.serviceClass = serviceClass;
480 }
481
Brian Stanke11f6d532016-07-05 16:17:59 -0400482 /**
483 * Returns the network identifier.
484 *
485 * @return network identifier
486 */
Brian Stanke86914282016-05-25 15:36:50 -0400487 public NetworkId networkId() {
488 return networkId;
489 }
490
Brian Stanke11f6d532016-07-05 16:17:59 -0400491 /**
492 * Returns the service class.
493 *
494 * @return service class
495 */
Brian Stanke86914282016-05-25 15:36:50 -0400496 public Class serviceClass() {
497 return serviceClass;
498 }
Claudine Chiue7f6b912017-02-24 14:13:30 -0500499
500 @Override
501 public int hashCode() {
502 return Objects.hash(networkId, serviceClass);
503 }
504
505 @Override
506 public boolean equals(Object obj) {
507 if (this == obj) {
508 return true;
509 }
510 if (obj instanceof ServiceKey) {
511 ServiceKey that = (ServiceKey) obj;
512 return Objects.equals(this.networkId, that.networkId) &&
513 Objects.equals(this.serviceClass, that.serviceClass);
514 }
515 return false;
516 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700517 }
518
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700519 @Override
yoonseon214963b2016-11-21 15:41:07 -0800520 protected VirtualNetworkProviderService
521 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700522 return new InternalVirtualNetworkProviderService(provider);
523 }
524
Brian Stankefb61df42016-07-25 11:47:51 -0400525 /**
526 * Service issued to registered virtual network providers so that they
527 * can interact with the core.
528 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700529 private class InternalVirtualNetworkProviderService
530 extends AbstractProviderService<VirtualNetworkProvider>
531 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400532 /**
533 * Constructor.
534 * @param provider virtual network provider
535 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700536 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
537 super(provider);
538 }
Brian Stanke4d579882016-04-22 13:28:46 -0400539
540 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400541 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400542 Set<TenantId> tenantIds = getTenantIds();
543 tenantIds.forEach(tenantId -> {
544 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
545
546 virtualNetworks.forEach(virtualNetwork -> {
547 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
548
549 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800550 if (isVirtualLinkInCluster(virtualNetwork.id(),
551 virtualLink, clusters)) {
552 store.updateLink(virtualLink, virtualLink.tunnelId(),
553 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400554 } else {
yoonseon214963b2016-11-21 15:41:07 -0800555 store.updateLink(virtualLink, virtualLink.tunnelId(),
556 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400557 }
558 });
559 });
560 });
561 }
562
563 /**
yoonseon214963b2016-11-21 15:41:07 -0800564 * Determines if the virtual link (both source and destination connect point)
565 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400566 *
567 * @param networkId virtual network identifier
568 * @param virtualLink virtual link
569 * @param clusters topology clusters
570 * @return true if the virtual link is in a cluster.
571 */
572 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
573 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800574 ConnectPoint srcPhysicalCp =
575 mapVirtualToPhysicalPort(networkId, virtualLink.src());
576 ConnectPoint dstPhysicalCp =
577 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400578
579 final boolean[] foundSrc = {false};
580 final boolean[] foundDst = {false};
581 clusters.forEach(connectPoints -> {
582 connectPoints.forEach(connectPoint -> {
583 if (connectPoint.equals(srcPhysicalCp)) {
584 foundSrc[0] = true;
585 } else if (connectPoint.equals(dstPhysicalCp)) {
586 foundDst[0] = true;
587 }
588 });
589 if (foundSrc[0] && foundDst[0]) {
590 return;
591 }
592 });
593 return foundSrc[0] && foundDst[0];
594 }
595
596 @Override
yoonseon214963b2016-11-21 15:41:07 -0800597 public void tunnelUp(NetworkId networkId, ConnectPoint src,
598 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400599 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
600 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
601 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
602 log.error("Src or dst virtual connection point was not found.");
603 }
604
605 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
606 if (virtualLink != null) {
607 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
608 }
Brian Stanke4d579882016-04-22 13:28:46 -0400609 }
610
611 @Override
yoonseon214963b2016-11-21 15:41:07 -0800612 public void tunnelDown(NetworkId networkId, ConnectPoint src,
613 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400614 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
615 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
616 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
617 log.error("Src or dst virtual connection point was not found.");
618 }
Brian Stanke4d579882016-04-22 13:28:46 -0400619
Brian Stanke612cebf2016-05-02 10:21:33 -0400620 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
621 if (virtualLink != null) {
622 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
623 }
Brian Stanke4d579882016-04-22 13:28:46 -0400624 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700625 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700626}