blob: 69f849efd09036c645d0a3b7d260ba1efb53e35a [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
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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070054import org.onosproject.net.ConnectPoint;
55import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040056import org.onosproject.net.HostId;
57import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040058import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070059import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040060import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050061import org.onosproject.net.flow.FlowRuleService;
yoonseon86bebed2017-02-03 15:23:57 -080062import org.onosproject.net.flowobjective.FlowObjectiveService;
Claudine Chiu465a2602017-03-17 18:33:36 -040063import org.onosproject.net.group.GroupService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040064import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040065import org.onosproject.net.intent.IntentService;
Brian Stanke86914282016-05-25 15:36:50 -040066import org.onosproject.net.link.LinkService;
yoonseon322c9c32016-12-07 16:47:02 -080067import org.onosproject.net.packet.PacketService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070068import org.onosproject.net.provider.AbstractListenerProviderRegistry;
69import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000070import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040071import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
Harold Huang3fcf7432017-05-16 16:21:08 +080075import java.util.HashSet;
Brian Stanke86914282016-05-25 15:36:50 -040076import java.util.Map;
Claudine Chiue7f6b912017-02-24 14:13:30 -050077import java.util.Objects;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070078import java.util.Set;
79
80import static com.google.common.base.Preconditions.checkNotNull;
81
82/**
83 * Implementation of the virtual network service.
84 */
85@Component(immediate = true)
86@Service
87public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080088 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
89 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
90 implements VirtualNetworkService, VirtualNetworkAdminService,
91 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070092
93 private final Logger log = LoggerFactory.getLogger(getClass());
94
95 private static final String TENANT_NULL = "Tenant ID cannot be null";
96 private static final String NETWORK_NULL = "Network ID cannot be null";
97 private static final String DEVICE_NULL = "Device ID cannot be null";
98 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
99
yoonseon322c9c32016-12-07 16:47:02 -0800100 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
101 "org.onosproject.virtual-network";
102
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected VirtualNetworkStore store;
105
Brian Stanke11f6d532016-07-05 16:17:59 -0400106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected IntentService intentService;
108
yoonseon322c9c32016-12-07 16:47:02 -0800109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected CoreService coreService;
111
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500112 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700113
yoonseonc6a69272017-01-12 18:22:20 -0800114 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
yoonseon322c9c32016-12-07 16:47:02 -0800115 private ApplicationId appId;
yoonseonc6a69272017-01-12 18:22:20 -0800116
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700117 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700118
Brian Stanke11f6d532016-07-05 16:17:59 -0400119 /**
120 * Only used for Junit test methods outside of this package.
121 *
122 * @param store virtual network store
123 */
124 public void setStore(VirtualNetworkStore store) {
125 this.store = store;
126 }
127
128 /**
129 * Only used for Junit test methods outside of this package.
130 *
131 * @param intentService intent service
132 */
133
134 public void setIntentService(IntentService intentService) {
135 this.intentService = intentService;
136 }
137
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700138 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400139 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500140 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Claudine Chiu465a2602017-03-17 18:33:36 -0400141 eventDispatcher.addSink(VirtualEvent.class,
142 VirtualListenerRegistryManager.getInstance());
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900143 store.setDelegate(delegate);
yoonseon322c9c32016-12-07 16:47:02 -0800144 appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700145 log.info("Started");
146 }
147
148 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400149 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700150 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500151 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Claudine Chiu465a2602017-03-17 18:33:36 -0400152 eventDispatcher.removeSink(VirtualEvent.class);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700153 log.info("Stopped");
154 }
155
156 @Override
157 public void registerTenantId(TenantId tenantId) {
158 checkNotNull(tenantId, TENANT_NULL);
159 store.addTenantId(tenantId);
160 }
161
162 @Override
163 public void unregisterTenantId(TenantId tenantId) {
164 checkNotNull(tenantId, TENANT_NULL);
165 store.removeTenantId(tenantId);
166 }
167
168 @Override
169 public Set<TenantId> getTenantIds() {
170 return store.getTenantIds();
171 }
172
173 @Override
174 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
175 checkNotNull(tenantId, TENANT_NULL);
176 return store.addNetwork(tenantId);
177 }
178
179 @Override
180 public void removeVirtualNetwork(NetworkId networkId) {
181 checkNotNull(networkId, NETWORK_NULL);
182 store.removeNetwork(networkId);
183 }
184
185 @Override
186 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
187 checkNotNull(networkId, NETWORK_NULL);
188 checkNotNull(deviceId, DEVICE_NULL);
189 return store.addDevice(networkId, deviceId);
190 }
191
192 @Override
193 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
194 checkNotNull(networkId, NETWORK_NULL);
195 checkNotNull(deviceId, DEVICE_NULL);
196 store.removeDevice(networkId, deviceId);
197 }
198
199 @Override
yoonseon214963b2016-11-21 15:41:07 -0800200 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
201 MacAddress mac, VlanId vlan,
202 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400203 checkNotNull(networkId, NETWORK_NULL);
204 checkNotNull(hostId, DEVICE_NULL);
205 return store.addHost(networkId, hostId, mac, vlan, location, ips);
206 }
207
208 @Override
209 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
210 checkNotNull(networkId, NETWORK_NULL);
211 checkNotNull(hostId, DEVICE_NULL);
212 store.removeHost(networkId, hostId);
213 }
214
215 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700216 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400217 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700218 checkNotNull(networkId, NETWORK_NULL);
219 checkNotNull(src, LINK_POINT_NULL);
220 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400221 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
222 checkNotNull(physicalSrc, LINK_POINT_NULL);
223 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
224 checkNotNull(physicalDst, LINK_POINT_NULL);
225
226 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
227 Link.State state = Link.State.INACTIVE;
228 if (provider != null) {
229 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
230 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
231 }
232 return store.addLink(networkId, src, dst, state, null);
233 }
234
235 /**
236 * Maps the virtual connect point to a physical connect point.
237 *
238 * @param networkId network identifier
239 * @param virtualCp virtual connect point
240 * @return physical connect point
241 */
242 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
243 ConnectPoint virtualCp) {
244 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
245 for (VirtualPort port : ports) {
246 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700247 return new ConnectPoint(port.realizedBy().deviceId(),
248 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400249 }
250 }
251 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700252 }
253
Brian Stanke612cebf2016-05-02 10:21:33 -0400254 /**
255 * Maps the physical connect point to a virtual connect point.
256 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400257 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400258 * @param physicalCp physical connect point
259 * @return virtual connect point
260 */
261 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400262 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400263 Set<VirtualPort> ports = store.getPorts(networkId, null);
264 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700265 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
266 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400267 return new ConnectPoint(port.element().id(), port.number());
268 }
269 }
270 return null;
271 }
272
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700273 @Override
yoonseon214963b2016-11-21 15:41:07 -0800274 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
275 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700276 checkNotNull(networkId, NETWORK_NULL);
277 checkNotNull(src, LINK_POINT_NULL);
278 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400279 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700280 }
281
282 @Override
283 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700284 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700285 checkNotNull(networkId, NETWORK_NULL);
286 checkNotNull(deviceId, DEVICE_NULL);
287 checkNotNull(portNumber, "Port description cannot be null");
288 return store.addPort(networkId, deviceId, portNumber, realizedBy);
289 }
290
291 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700292 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
293 PortNumber portNumber, ConnectPoint realizedBy) {
294 checkNotNull(networkId, NETWORK_NULL);
295 checkNotNull(deviceId, DEVICE_NULL);
296 checkNotNull(portNumber, "Port description cannot be null");
297 checkNotNull(realizedBy, "Physical port description cannot be null");
298
299 store.bindPort(networkId, deviceId, portNumber, realizedBy);
300 }
301
302 @Override
yoonseon214963b2016-11-21 15:41:07 -0800303 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
304 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700305 checkNotNull(networkId, NETWORK_NULL);
306 checkNotNull(deviceId, DEVICE_NULL);
307 checkNotNull(portNumber, "Port number cannot be null");
308 store.removePort(networkId, deviceId, portNumber);
309 }
310
311 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800312 public ServiceDirectory getServiceDirectory() {
313 return serviceDirectory;
314 }
315
316 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700317 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
318 checkNotNull(tenantId, TENANT_NULL);
319 return store.getNetworks(tenantId);
320 }
321
Brian Stanke11f6d532016-07-05 16:17:59 -0400322 /**
323 * Returns the virtual network matching the network identifier.
324 *
325 * @param networkId network identifier
326 * @return virtual network
327 */
Brian Stanke86914282016-05-25 15:36:50 -0400328 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
329 checkNotNull(networkId, NETWORK_NULL);
330 return store.getNetwork(networkId);
331 }
332
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700333 @Override
334 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
335 checkNotNull(networkId, NETWORK_NULL);
336 return store.getDevices(networkId);
337 }
338
339 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400340 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
341 checkNotNull(networkId, NETWORK_NULL);
342 return store.getHosts(networkId);
343 }
344
345 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700346 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
347 checkNotNull(networkId, NETWORK_NULL);
348 return store.getLinks(networkId);
349 }
350
351 @Override
352 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
353 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700354 return store.getPorts(networkId, deviceId);
355 }
356
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700357 @Override
Harold Huang3fcf7432017-05-16 16:21:08 +0800358 public Set<DeviceId> getPhysicalDevices(NetworkId networkId, DeviceId deviceId) {
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700359 checkNotNull(networkId, "Network ID cannot be null");
Harold Huang3fcf7432017-05-16 16:21:08 +0800360 checkNotNull(deviceId, "Virtual device ID cannot be null");
361 Set<VirtualPort> virtualPortSet = getVirtualPorts(networkId, deviceId);
362 Set<DeviceId> physicalDeviceSet = new HashSet<>();
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700363
364 virtualPortSet.forEach(virtualPort -> {
365 if (virtualPort.realizedBy() != null) {
366 physicalDeviceSet.add(virtualPort.realizedBy().deviceId());
367 }
368 });
369
Harold Huang3fcf7432017-05-16 16:21:08 +0800370 return ImmutableSet.copyOf(physicalDeviceSet);
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700371 }
372
Brian Stanke86914282016-05-25 15:36:50 -0400373 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
374
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700375 @Override
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900376 @SuppressWarnings("unchecked")
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700377 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
378 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400379 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
380 VnetService service = lookup(serviceKey);
381 if (service == null) {
382 service = create(serviceKey);
383 }
384 return (T) service;
385 }
386
yoonseon322c9c32016-12-07 16:47:02 -0800387 @Override
388 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
389 return appId;
390 }
391
Brian Stanke11f6d532016-07-05 16:17:59 -0400392 /**
393 * Returns the Vnet service matching the service key.
394 *
395 * @param serviceKey service key
396 * @return vnet service
397 */
Brian Stanke86914282016-05-25 15:36:50 -0400398 private VnetService lookup(ServiceKey serviceKey) {
399 return networkServices.get(serviceKey);
400 }
401
Brian Stanke11f6d532016-07-05 16:17:59 -0400402 /**
403 * Creates a new service key using the specified network identifier and service class.
404 *
405 * @param networkId network identifier
406 * @param serviceClass service class
407 * @param <T> type of service
408 * @return service key
409 */
Brian Stanke86914282016-05-25 15:36:50 -0400410 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
411 return new ServiceKey(networkId, serviceClass);
412 }
413
414
Brian Stanke11f6d532016-07-05 16:17:59 -0400415 /**
416 * Create a new vnet service instance.
417 *
418 * @param serviceKey service key
419 * @return vnet service
420 */
Brian Stanke86914282016-05-25 15:36:50 -0400421 private VnetService create(ServiceKey serviceKey) {
422 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400423 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800424
Brian Stanke86914282016-05-25 15:36:50 -0400425 VnetService service;
426 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800427 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400428 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800429 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400430 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800431 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400432 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800433 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400434 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800435 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000436 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800437 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500438 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800439 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800440 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
441 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800442 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
443 service = new VirtualNetworkGroupManager(this, network.id());
yoonseon86bebed2017-02-03 15:23:57 -0800444 } else if (serviceKey.serviceClass.equals(FlowObjectiveService.class)) {
445 service = new VirtualNetworkFlowObjectiveManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400446 } else {
447 return null;
448 }
449 networkServices.put(serviceKey, service);
450 return service;
451 }
452
Brian Stanke11f6d532016-07-05 16:17:59 -0400453 /**
454 * Service key class.
455 */
Claudine Chiu9a18f492017-02-27 15:57:06 -0500456 private static class ServiceKey {
Brian Stanke86914282016-05-25 15:36:50 -0400457 final NetworkId networkId;
458 final Class serviceClass;
459
Brian Stanke11f6d532016-07-05 16:17:59 -0400460 /**
461 * Constructor for service key.
462 *
463 * @param networkId network identifier
464 * @param serviceClass service class
465 */
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900466 ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800467
Brian Stanke86914282016-05-25 15:36:50 -0400468 checkNotNull(networkId, NETWORK_NULL);
469 this.networkId = networkId;
470 this.serviceClass = serviceClass;
471 }
472
Brian Stanke11f6d532016-07-05 16:17:59 -0400473 /**
474 * Returns the network identifier.
475 *
476 * @return network identifier
477 */
Brian Stanke86914282016-05-25 15:36:50 -0400478 public NetworkId networkId() {
479 return networkId;
480 }
481
Brian Stanke11f6d532016-07-05 16:17:59 -0400482 /**
483 * Returns the service class.
484 *
485 * @return service class
486 */
Brian Stanke86914282016-05-25 15:36:50 -0400487 public Class serviceClass() {
488 return serviceClass;
489 }
Claudine Chiue7f6b912017-02-24 14:13:30 -0500490
491 @Override
492 public int hashCode() {
493 return Objects.hash(networkId, serviceClass);
494 }
495
496 @Override
497 public boolean equals(Object obj) {
498 if (this == obj) {
499 return true;
500 }
501 if (obj instanceof ServiceKey) {
502 ServiceKey that = (ServiceKey) obj;
503 return Objects.equals(this.networkId, that.networkId) &&
504 Objects.equals(this.serviceClass, that.serviceClass);
505 }
506 return false;
507 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700508 }
509
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700510 @Override
yoonseon214963b2016-11-21 15:41:07 -0800511 protected VirtualNetworkProviderService
512 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700513 return new InternalVirtualNetworkProviderService(provider);
514 }
515
Brian Stankefb61df42016-07-25 11:47:51 -0400516 /**
517 * Service issued to registered virtual network providers so that they
518 * can interact with the core.
519 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700520 private class InternalVirtualNetworkProviderService
521 extends AbstractProviderService<VirtualNetworkProvider>
522 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400523 /**
524 * Constructor.
525 * @param provider virtual network provider
526 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700527 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
528 super(provider);
529 }
Brian Stanke4d579882016-04-22 13:28:46 -0400530
531 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400532 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400533 Set<TenantId> tenantIds = getTenantIds();
534 tenantIds.forEach(tenantId -> {
535 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
536
537 virtualNetworks.forEach(virtualNetwork -> {
538 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
539
540 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800541 if (isVirtualLinkInCluster(virtualNetwork.id(),
542 virtualLink, clusters)) {
543 store.updateLink(virtualLink, virtualLink.tunnelId(),
544 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400545 } else {
yoonseon214963b2016-11-21 15:41:07 -0800546 store.updateLink(virtualLink, virtualLink.tunnelId(),
547 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400548 }
549 });
550 });
551 });
552 }
553
554 /**
yoonseon214963b2016-11-21 15:41:07 -0800555 * Determines if the virtual link (both source and destination connect point)
556 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400557 *
558 * @param networkId virtual network identifier
559 * @param virtualLink virtual link
560 * @param clusters topology clusters
561 * @return true if the virtual link is in a cluster.
562 */
563 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
564 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800565 ConnectPoint srcPhysicalCp =
566 mapVirtualToPhysicalPort(networkId, virtualLink.src());
567 ConnectPoint dstPhysicalCp =
568 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400569
570 final boolean[] foundSrc = {false};
571 final boolean[] foundDst = {false};
572 clusters.forEach(connectPoints -> {
573 connectPoints.forEach(connectPoint -> {
574 if (connectPoint.equals(srcPhysicalCp)) {
575 foundSrc[0] = true;
576 } else if (connectPoint.equals(dstPhysicalCp)) {
577 foundDst[0] = true;
578 }
579 });
580 if (foundSrc[0] && foundDst[0]) {
581 return;
582 }
583 });
584 return foundSrc[0] && foundDst[0];
585 }
586
587 @Override
yoonseon214963b2016-11-21 15:41:07 -0800588 public void tunnelUp(NetworkId networkId, ConnectPoint src,
589 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400590 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
591 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
592 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
593 log.error("Src or dst virtual connection point was not found.");
594 }
595
596 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
597 if (virtualLink != null) {
598 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
599 }
Brian Stanke4d579882016-04-22 13:28:46 -0400600 }
601
602 @Override
yoonseon214963b2016-11-21 15:41:07 -0800603 public void tunnelDown(NetworkId networkId, ConnectPoint src,
604 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400605 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
606 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
607 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
608 log.error("Src or dst virtual connection point was not found.");
609 }
Brian Stanke4d579882016-04-22 13:28:46 -0400610
Brian Stanke612cebf2016-05-02 10:21:33 -0400611 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
612 if (virtualLink != null) {
613 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
614 }
Brian Stanke4d579882016-04-22 13:28:46 -0400615 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700616 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700617}