blob: 20b6cebb331fffb9d1883c1a241c271a5c60fde0 [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
yoonseon214963b2016-11-21 15:41:07 -0800294 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
295 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700296 checkNotNull(networkId, NETWORK_NULL);
297 checkNotNull(deviceId, DEVICE_NULL);
298 checkNotNull(portNumber, "Port number cannot be null");
299 store.removePort(networkId, deviceId, portNumber);
300 }
301
302 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800303 public ServiceDirectory getServiceDirectory() {
304 return serviceDirectory;
305 }
306
307 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700308 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
309 checkNotNull(tenantId, TENANT_NULL);
310 return store.getNetworks(tenantId);
311 }
312
Brian Stanke11f6d532016-07-05 16:17:59 -0400313 /**
314 * Returns the virtual network matching the network identifier.
315 *
316 * @param networkId network identifier
317 * @return virtual network
318 */
Brian Stanke86914282016-05-25 15:36:50 -0400319 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
320 checkNotNull(networkId, NETWORK_NULL);
321 return store.getNetwork(networkId);
322 }
323
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700324 @Override
325 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
326 checkNotNull(networkId, NETWORK_NULL);
327 return store.getDevices(networkId);
328 }
329
330 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400331 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
332 checkNotNull(networkId, NETWORK_NULL);
333 return store.getHosts(networkId);
334 }
335
336 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700337 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
338 checkNotNull(networkId, NETWORK_NULL);
339 return store.getLinks(networkId);
340 }
341
342 @Override
343 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
344 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700345 return store.getPorts(networkId, deviceId);
346 }
347
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700348 @Override
Harold Huang3fcf7432017-05-16 16:21:08 +0800349 public Set<DeviceId> getPhysicalDevices(NetworkId networkId, DeviceId deviceId) {
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700350 checkNotNull(networkId, "Network ID cannot be null");
Harold Huang3fcf7432017-05-16 16:21:08 +0800351 checkNotNull(deviceId, "Virtual device ID cannot be null");
352 Set<VirtualPort> virtualPortSet = getVirtualPorts(networkId, deviceId);
353 Set<DeviceId> physicalDeviceSet = new HashSet<>();
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700354
355 virtualPortSet.forEach(virtualPort -> {
356 if (virtualPort.realizedBy() != null) {
357 physicalDeviceSet.add(virtualPort.realizedBy().deviceId());
358 }
359 });
360
Harold Huang3fcf7432017-05-16 16:21:08 +0800361 return ImmutableSet.copyOf(physicalDeviceSet);
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700362 }
363
Brian Stanke86914282016-05-25 15:36:50 -0400364 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
365
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700366 @Override
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900367 @SuppressWarnings("unchecked")
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700368 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
369 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400370 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
371 VnetService service = lookup(serviceKey);
372 if (service == null) {
373 service = create(serviceKey);
374 }
375 return (T) service;
376 }
377
yoonseon322c9c32016-12-07 16:47:02 -0800378 @Override
379 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
380 return appId;
381 }
382
Brian Stanke11f6d532016-07-05 16:17:59 -0400383 /**
384 * Returns the Vnet service matching the service key.
385 *
386 * @param serviceKey service key
387 * @return vnet service
388 */
Brian Stanke86914282016-05-25 15:36:50 -0400389 private VnetService lookup(ServiceKey serviceKey) {
390 return networkServices.get(serviceKey);
391 }
392
Brian Stanke11f6d532016-07-05 16:17:59 -0400393 /**
394 * Creates a new service key using the specified network identifier and service class.
395 *
396 * @param networkId network identifier
397 * @param serviceClass service class
398 * @param <T> type of service
399 * @return service key
400 */
Brian Stanke86914282016-05-25 15:36:50 -0400401 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
402 return new ServiceKey(networkId, serviceClass);
403 }
404
405
Brian Stanke11f6d532016-07-05 16:17:59 -0400406 /**
407 * Create a new vnet service instance.
408 *
409 * @param serviceKey service key
410 * @return vnet service
411 */
Brian Stanke86914282016-05-25 15:36:50 -0400412 private VnetService create(ServiceKey serviceKey) {
413 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400414 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800415
Brian Stanke86914282016-05-25 15:36:50 -0400416 VnetService service;
417 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800418 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400419 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800420 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400421 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800422 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400423 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800424 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400425 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800426 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000427 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800428 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500429 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800430 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800431 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
432 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800433 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
434 service = new VirtualNetworkGroupManager(this, network.id());
yoonseon94672112017-01-31 13:46:21 -0800435 } else if (serviceKey.serviceClass.equals(MeterService.class)) {
436 service = new VirtualNetworkMeterManager(this, network.id());
yoonseon86bebed2017-02-03 15:23:57 -0800437 } else if (serviceKey.serviceClass.equals(FlowObjectiveService.class)) {
438 service = new VirtualNetworkFlowObjectiveManager(this, network.id());
Harold Huang222c6ec2017-06-02 15:02:49 +0800439 } else if (serviceKey.serviceClass.equals(MastershipService.class) ||
440 serviceKey.serviceClass.equals(MastershipAdminService.class) ||
441 serviceKey.serviceClass.equals(MastershipTermService.class)) {
Yoonseon Hana578d762017-05-08 13:42:02 -0700442 service = new VirtualNetworkMastershipManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400443 } else {
444 return null;
445 }
446 networkServices.put(serviceKey, service);
447 return service;
448 }
449
Brian Stanke11f6d532016-07-05 16:17:59 -0400450 /**
451 * Service key class.
452 */
Claudine Chiu9a18f492017-02-27 15:57:06 -0500453 private static class ServiceKey {
Brian Stanke86914282016-05-25 15:36:50 -0400454 final NetworkId networkId;
455 final Class serviceClass;
456
Brian Stanke11f6d532016-07-05 16:17:59 -0400457 /**
458 * Constructor for service key.
459 *
460 * @param networkId network identifier
461 * @param serviceClass service class
462 */
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900463 ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800464
Brian Stanke86914282016-05-25 15:36:50 -0400465 checkNotNull(networkId, NETWORK_NULL);
466 this.networkId = networkId;
467 this.serviceClass = serviceClass;
468 }
469
Brian Stanke11f6d532016-07-05 16:17:59 -0400470 /**
471 * Returns the network identifier.
472 *
473 * @return network identifier
474 */
Brian Stanke86914282016-05-25 15:36:50 -0400475 public NetworkId networkId() {
476 return networkId;
477 }
478
Brian Stanke11f6d532016-07-05 16:17:59 -0400479 /**
480 * Returns the service class.
481 *
482 * @return service class
483 */
Brian Stanke86914282016-05-25 15:36:50 -0400484 public Class serviceClass() {
485 return serviceClass;
486 }
Claudine Chiue7f6b912017-02-24 14:13:30 -0500487
488 @Override
489 public int hashCode() {
490 return Objects.hash(networkId, serviceClass);
491 }
492
493 @Override
494 public boolean equals(Object obj) {
495 if (this == obj) {
496 return true;
497 }
498 if (obj instanceof ServiceKey) {
499 ServiceKey that = (ServiceKey) obj;
500 return Objects.equals(this.networkId, that.networkId) &&
501 Objects.equals(this.serviceClass, that.serviceClass);
502 }
503 return false;
504 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700505 }
506
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700507 @Override
yoonseon214963b2016-11-21 15:41:07 -0800508 protected VirtualNetworkProviderService
509 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700510 return new InternalVirtualNetworkProviderService(provider);
511 }
512
Brian Stankefb61df42016-07-25 11:47:51 -0400513 /**
514 * Service issued to registered virtual network providers so that they
515 * can interact with the core.
516 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700517 private class InternalVirtualNetworkProviderService
518 extends AbstractProviderService<VirtualNetworkProvider>
519 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400520 /**
521 * Constructor.
522 * @param provider virtual network provider
523 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700524 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
525 super(provider);
526 }
Brian Stanke4d579882016-04-22 13:28:46 -0400527
528 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400529 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400530 Set<TenantId> tenantIds = getTenantIds();
531 tenantIds.forEach(tenantId -> {
532 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
533
534 virtualNetworks.forEach(virtualNetwork -> {
535 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
536
537 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800538 if (isVirtualLinkInCluster(virtualNetwork.id(),
539 virtualLink, clusters)) {
540 store.updateLink(virtualLink, virtualLink.tunnelId(),
541 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400542 } else {
yoonseon214963b2016-11-21 15:41:07 -0800543 store.updateLink(virtualLink, virtualLink.tunnelId(),
544 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400545 }
546 });
547 });
548 });
549 }
550
551 /**
yoonseon214963b2016-11-21 15:41:07 -0800552 * Determines if the virtual link (both source and destination connect point)
553 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400554 *
555 * @param networkId virtual network identifier
556 * @param virtualLink virtual link
557 * @param clusters topology clusters
558 * @return true if the virtual link is in a cluster.
559 */
560 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
561 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800562 ConnectPoint srcPhysicalCp =
563 mapVirtualToPhysicalPort(networkId, virtualLink.src());
564 ConnectPoint dstPhysicalCp =
565 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400566
567 final boolean[] foundSrc = {false};
568 final boolean[] foundDst = {false};
569 clusters.forEach(connectPoints -> {
570 connectPoints.forEach(connectPoint -> {
571 if (connectPoint.equals(srcPhysicalCp)) {
572 foundSrc[0] = true;
573 } else if (connectPoint.equals(dstPhysicalCp)) {
574 foundDst[0] = true;
575 }
576 });
577 if (foundSrc[0] && foundDst[0]) {
578 return;
579 }
580 });
581 return foundSrc[0] && foundDst[0];
582 }
583
584 @Override
yoonseon214963b2016-11-21 15:41:07 -0800585 public void tunnelUp(NetworkId networkId, ConnectPoint src,
586 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400587 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
588 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
589 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
590 log.error("Src or dst virtual connection point was not found.");
591 }
592
593 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
594 if (virtualLink != null) {
595 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
596 }
Brian Stanke4d579882016-04-22 13:28:46 -0400597 }
598
599 @Override
yoonseon214963b2016-11-21 15:41:07 -0800600 public void tunnelDown(NetworkId networkId, ConnectPoint src,
601 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400602 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
603 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
604 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
605 log.error("Src or dst virtual connection point was not found.");
606 }
Brian Stanke4d579882016-04-22 13:28:46 -0400607
Brian Stanke612cebf2016-05-02 10:21:33 -0400608 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
609 if (virtualLink != null) {
610 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
611 }
Brian Stanke4d579882016-04-22 13:28:46 -0400612 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700613 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700614}