blob: d57801b93064160f018d611174f783d0fc0b9a68 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska33979fd2015-07-31 11:41:14 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.incubator.net.virtual.impl;
17
Brian Stanke86914282016-05-25 15:36:50 -040018import com.google.common.collect.Maps;
Yoonseon Hanffcc32f2017-05-03 14:42:17 -070019import com.google.common.collect.Sets;
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
Brian Stanke86914282016-05-25 15:36:50 -040075import java.util.Map;
Claudine Chiue7f6b912017-02-24 14:13:30 -050076import java.util.Objects;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070077import java.util.Set;
78
79import static com.google.common.base.Preconditions.checkNotNull;
80
81/**
82 * Implementation of the virtual network service.
83 */
84@Component(immediate = true)
85@Service
86public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080087 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
88 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
89 implements VirtualNetworkService, VirtualNetworkAdminService,
90 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070091
92 private final Logger log = LoggerFactory.getLogger(getClass());
93
94 private static final String TENANT_NULL = "Tenant ID cannot be null";
95 private static final String NETWORK_NULL = "Network ID cannot be null";
96 private static final String DEVICE_NULL = "Device ID cannot be null";
97 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
98
yoonseon322c9c32016-12-07 16:47:02 -080099 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
100 "org.onosproject.virtual-network";
101
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected VirtualNetworkStore store;
104
Brian Stanke11f6d532016-07-05 16:17:59 -0400105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected IntentService intentService;
107
yoonseon322c9c32016-12-07 16:47:02 -0800108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected CoreService coreService;
110
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500111 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700112
yoonseonc6a69272017-01-12 18:22:20 -0800113 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
yoonseon322c9c32016-12-07 16:47:02 -0800114 private ApplicationId appId;
yoonseonc6a69272017-01-12 18:22:20 -0800115
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700116 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700117
Brian Stanke11f6d532016-07-05 16:17:59 -0400118 /**
119 * Only used for Junit test methods outside of this package.
120 *
121 * @param store virtual network store
122 */
123 public void setStore(VirtualNetworkStore store) {
124 this.store = store;
125 }
126
127 /**
128 * Only used for Junit test methods outside of this package.
129 *
130 * @param intentService intent service
131 */
132
133 public void setIntentService(IntentService intentService) {
134 this.intentService = intentService;
135 }
136
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700137 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400138 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500139 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Claudine Chiu465a2602017-03-17 18:33:36 -0400140 eventDispatcher.addSink(VirtualEvent.class,
141 VirtualListenerRegistryManager.getInstance());
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900142 store.setDelegate(delegate);
yoonseon322c9c32016-12-07 16:47:02 -0800143 appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700144 log.info("Started");
145 }
146
147 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400148 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700149 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500150 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Claudine Chiu465a2602017-03-17 18:33:36 -0400151 eventDispatcher.removeSink(VirtualEvent.class);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700152 log.info("Stopped");
153 }
154
155 @Override
156 public void registerTenantId(TenantId tenantId) {
157 checkNotNull(tenantId, TENANT_NULL);
158 store.addTenantId(tenantId);
159 }
160
161 @Override
162 public void unregisterTenantId(TenantId tenantId) {
163 checkNotNull(tenantId, TENANT_NULL);
164 store.removeTenantId(tenantId);
165 }
166
167 @Override
168 public Set<TenantId> getTenantIds() {
169 return store.getTenantIds();
170 }
171
172 @Override
173 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
174 checkNotNull(tenantId, TENANT_NULL);
175 return store.addNetwork(tenantId);
176 }
177
178 @Override
179 public void removeVirtualNetwork(NetworkId networkId) {
180 checkNotNull(networkId, NETWORK_NULL);
181 store.removeNetwork(networkId);
182 }
183
184 @Override
185 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
186 checkNotNull(networkId, NETWORK_NULL);
187 checkNotNull(deviceId, DEVICE_NULL);
188 return store.addDevice(networkId, deviceId);
189 }
190
191 @Override
192 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
193 checkNotNull(networkId, NETWORK_NULL);
194 checkNotNull(deviceId, DEVICE_NULL);
195 store.removeDevice(networkId, deviceId);
196 }
197
198 @Override
yoonseon214963b2016-11-21 15:41:07 -0800199 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
200 MacAddress mac, VlanId vlan,
201 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400202 checkNotNull(networkId, NETWORK_NULL);
203 checkNotNull(hostId, DEVICE_NULL);
204 return store.addHost(networkId, hostId, mac, vlan, location, ips);
205 }
206
207 @Override
208 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
209 checkNotNull(networkId, NETWORK_NULL);
210 checkNotNull(hostId, DEVICE_NULL);
211 store.removeHost(networkId, hostId);
212 }
213
214 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700215 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400216 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700217 checkNotNull(networkId, NETWORK_NULL);
218 checkNotNull(src, LINK_POINT_NULL);
219 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400220 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
221 checkNotNull(physicalSrc, LINK_POINT_NULL);
222 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
223 checkNotNull(physicalDst, LINK_POINT_NULL);
224
225 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
226 Link.State state = Link.State.INACTIVE;
227 if (provider != null) {
228 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
229 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
230 }
231 return store.addLink(networkId, src, dst, state, null);
232 }
233
234 /**
235 * Maps the virtual connect point to a physical connect point.
236 *
237 * @param networkId network identifier
238 * @param virtualCp virtual connect point
239 * @return physical connect point
240 */
241 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
242 ConnectPoint virtualCp) {
243 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
244 for (VirtualPort port : ports) {
245 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700246 return new ConnectPoint(port.realizedBy().deviceId(),
247 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400248 }
249 }
250 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700251 }
252
Brian Stanke612cebf2016-05-02 10:21:33 -0400253 /**
254 * Maps the physical connect point to a virtual connect point.
255 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400256 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400257 * @param physicalCp physical connect point
258 * @return virtual connect point
259 */
260 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400261 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400262 Set<VirtualPort> ports = store.getPorts(networkId, null);
263 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700264 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
265 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400266 return new ConnectPoint(port.element().id(), port.number());
267 }
268 }
269 return null;
270 }
271
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700272 @Override
yoonseon214963b2016-11-21 15:41:07 -0800273 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
274 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700275 checkNotNull(networkId, NETWORK_NULL);
276 checkNotNull(src, LINK_POINT_NULL);
277 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400278 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700279 }
280
281 @Override
282 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700283 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700284 checkNotNull(networkId, NETWORK_NULL);
285 checkNotNull(deviceId, DEVICE_NULL);
286 checkNotNull(portNumber, "Port description cannot be null");
287 return store.addPort(networkId, deviceId, portNumber, realizedBy);
288 }
289
290 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700291 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
292 PortNumber portNumber, ConnectPoint realizedBy) {
293 checkNotNull(networkId, NETWORK_NULL);
294 checkNotNull(deviceId, DEVICE_NULL);
295 checkNotNull(portNumber, "Port description cannot be null");
296 checkNotNull(realizedBy, "Physical port description cannot be null");
297
298 store.bindPort(networkId, deviceId, portNumber, realizedBy);
299 }
300
301 @Override
yoonseon214963b2016-11-21 15:41:07 -0800302 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
303 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700304 checkNotNull(networkId, NETWORK_NULL);
305 checkNotNull(deviceId, DEVICE_NULL);
306 checkNotNull(portNumber, "Port number cannot be null");
307 store.removePort(networkId, deviceId, portNumber);
308 }
309
310 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800311 public ServiceDirectory getServiceDirectory() {
312 return serviceDirectory;
313 }
314
315 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700316 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
317 checkNotNull(tenantId, TENANT_NULL);
318 return store.getNetworks(tenantId);
319 }
320
Brian Stanke11f6d532016-07-05 16:17:59 -0400321 /**
322 * Returns the virtual network matching the network identifier.
323 *
324 * @param networkId network identifier
325 * @return virtual network
326 */
Brian Stanke86914282016-05-25 15:36:50 -0400327 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
328 checkNotNull(networkId, NETWORK_NULL);
329 return store.getNetwork(networkId);
330 }
331
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700332 @Override
333 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
334 checkNotNull(networkId, NETWORK_NULL);
335 return store.getDevices(networkId);
336 }
337
338 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400339 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
340 checkNotNull(networkId, NETWORK_NULL);
341 return store.getHosts(networkId);
342 }
343
344 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700345 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
346 checkNotNull(networkId, NETWORK_NULL);
347 return store.getLinks(networkId);
348 }
349
350 @Override
351 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
352 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700353 return store.getPorts(networkId, deviceId);
354 }
355
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700356 @Override
357 public Set<DeviceId> getPhysicalDevices(NetworkId networkId,
358 VirtualDevice virtualDevice) {
359 checkNotNull(networkId, "Network ID cannot be null");
360 checkNotNull(virtualDevice, "Virtual device cannot be null");
361 Set<VirtualPort> virtualPortSet =
362 getVirtualPorts(networkId, virtualDevice.id());
363 Set<DeviceId> physicalDeviceSet = Sets.newConcurrentHashSet();
364
365 virtualPortSet.forEach(virtualPort -> {
366 if (virtualPort.realizedBy() != null) {
367 physicalDeviceSet.add(virtualPort.realizedBy().deviceId());
368 }
369 });
370
371 return physicalDeviceSet;
372 }
373
Brian Stanke86914282016-05-25 15:36:50 -0400374 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
375
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700376 @Override
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900377 @SuppressWarnings("unchecked")
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700378 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
379 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400380 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
381 VnetService service = lookup(serviceKey);
382 if (service == null) {
383 service = create(serviceKey);
384 }
385 return (T) service;
386 }
387
yoonseon322c9c32016-12-07 16:47:02 -0800388 @Override
389 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
390 return appId;
391 }
392
Brian Stanke11f6d532016-07-05 16:17:59 -0400393 /**
394 * Returns the Vnet service matching the service key.
395 *
396 * @param serviceKey service key
397 * @return vnet service
398 */
Brian Stanke86914282016-05-25 15:36:50 -0400399 private VnetService lookup(ServiceKey serviceKey) {
400 return networkServices.get(serviceKey);
401 }
402
Brian Stanke11f6d532016-07-05 16:17:59 -0400403 /**
404 * Creates a new service key using the specified network identifier and service class.
405 *
406 * @param networkId network identifier
407 * @param serviceClass service class
408 * @param <T> type of service
409 * @return service key
410 */
Brian Stanke86914282016-05-25 15:36:50 -0400411 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
412 return new ServiceKey(networkId, serviceClass);
413 }
414
415
Brian Stanke11f6d532016-07-05 16:17:59 -0400416 /**
417 * Create a new vnet service instance.
418 *
419 * @param serviceKey service key
420 * @return vnet service
421 */
Brian Stanke86914282016-05-25 15:36:50 -0400422 private VnetService create(ServiceKey serviceKey) {
423 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400424 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800425
Brian Stanke86914282016-05-25 15:36:50 -0400426 VnetService service;
427 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800428 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400429 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800430 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400431 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800432 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400433 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800434 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400435 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800436 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000437 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800438 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500439 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800440 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800441 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
442 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800443 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
444 service = new VirtualNetworkGroupManager(this, network.id());
yoonseon86bebed2017-02-03 15:23:57 -0800445 } else if (serviceKey.serviceClass.equals(FlowObjectiveService.class)) {
446 service = new VirtualNetworkFlowObjectiveManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400447 } else {
448 return null;
449 }
450 networkServices.put(serviceKey, service);
451 return service;
452 }
453
Brian Stanke11f6d532016-07-05 16:17:59 -0400454 /**
455 * Service key class.
456 */
Claudine Chiu9a18f492017-02-27 15:57:06 -0500457 private static class ServiceKey {
Brian Stanke86914282016-05-25 15:36:50 -0400458 final NetworkId networkId;
459 final Class serviceClass;
460
Brian Stanke11f6d532016-07-05 16:17:59 -0400461 /**
462 * Constructor for service key.
463 *
464 * @param networkId network identifier
465 * @param serviceClass service class
466 */
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900467 ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800468
Brian Stanke86914282016-05-25 15:36:50 -0400469 checkNotNull(networkId, NETWORK_NULL);
470 this.networkId = networkId;
471 this.serviceClass = serviceClass;
472 }
473
Brian Stanke11f6d532016-07-05 16:17:59 -0400474 /**
475 * Returns the network identifier.
476 *
477 * @return network identifier
478 */
Brian Stanke86914282016-05-25 15:36:50 -0400479 public NetworkId networkId() {
480 return networkId;
481 }
482
Brian Stanke11f6d532016-07-05 16:17:59 -0400483 /**
484 * Returns the service class.
485 *
486 * @return service class
487 */
Brian Stanke86914282016-05-25 15:36:50 -0400488 public Class serviceClass() {
489 return serviceClass;
490 }
Claudine Chiue7f6b912017-02-24 14:13:30 -0500491
492 @Override
493 public int hashCode() {
494 return Objects.hash(networkId, serviceClass);
495 }
496
497 @Override
498 public boolean equals(Object obj) {
499 if (this == obj) {
500 return true;
501 }
502 if (obj instanceof ServiceKey) {
503 ServiceKey that = (ServiceKey) obj;
504 return Objects.equals(this.networkId, that.networkId) &&
505 Objects.equals(this.serviceClass, that.serviceClass);
506 }
507 return false;
508 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700509 }
510
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700511 @Override
yoonseon214963b2016-11-21 15:41:07 -0800512 protected VirtualNetworkProviderService
513 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700514 return new InternalVirtualNetworkProviderService(provider);
515 }
516
Brian Stankefb61df42016-07-25 11:47:51 -0400517 /**
518 * Service issued to registered virtual network providers so that they
519 * can interact with the core.
520 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700521 private class InternalVirtualNetworkProviderService
522 extends AbstractProviderService<VirtualNetworkProvider>
523 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400524 /**
525 * Constructor.
526 * @param provider virtual network provider
527 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700528 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
529 super(provider);
530 }
Brian Stanke4d579882016-04-22 13:28:46 -0400531
532 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400533 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400534 Set<TenantId> tenantIds = getTenantIds();
535 tenantIds.forEach(tenantId -> {
536 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
537
538 virtualNetworks.forEach(virtualNetwork -> {
539 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
540
541 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800542 if (isVirtualLinkInCluster(virtualNetwork.id(),
543 virtualLink, clusters)) {
544 store.updateLink(virtualLink, virtualLink.tunnelId(),
545 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400546 } else {
yoonseon214963b2016-11-21 15:41:07 -0800547 store.updateLink(virtualLink, virtualLink.tunnelId(),
548 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400549 }
550 });
551 });
552 });
553 }
554
555 /**
yoonseon214963b2016-11-21 15:41:07 -0800556 * Determines if the virtual link (both source and destination connect point)
557 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400558 *
559 * @param networkId virtual network identifier
560 * @param virtualLink virtual link
561 * @param clusters topology clusters
562 * @return true if the virtual link is in a cluster.
563 */
564 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
565 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800566 ConnectPoint srcPhysicalCp =
567 mapVirtualToPhysicalPort(networkId, virtualLink.src());
568 ConnectPoint dstPhysicalCp =
569 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400570
571 final boolean[] foundSrc = {false};
572 final boolean[] foundDst = {false};
573 clusters.forEach(connectPoints -> {
574 connectPoints.forEach(connectPoint -> {
575 if (connectPoint.equals(srcPhysicalCp)) {
576 foundSrc[0] = true;
577 } else if (connectPoint.equals(dstPhysicalCp)) {
578 foundDst[0] = true;
579 }
580 });
581 if (foundSrc[0] && foundDst[0]) {
582 return;
583 }
584 });
585 return foundSrc[0] && foundDst[0];
586 }
587
588 @Override
yoonseon214963b2016-11-21 15:41:07 -0800589 public void tunnelUp(NetworkId networkId, ConnectPoint src,
590 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400591 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
592 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
593 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
594 log.error("Src or dst virtual connection point was not found.");
595 }
596
597 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
598 if (virtualLink != null) {
599 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
600 }
Brian Stanke4d579882016-04-22 13:28:46 -0400601 }
602
603 @Override
yoonseon214963b2016-11-21 15:41:07 -0800604 public void tunnelDown(NetworkId networkId, ConnectPoint src,
605 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400606 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
607 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
608 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
609 log.error("Src or dst virtual connection point was not found.");
610 }
Brian Stanke4d579882016-04-22 13:28:46 -0400611
Brian Stanke612cebf2016-05-02 10:21:33 -0400612 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
613 if (virtualLink != null) {
614 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
615 }
Brian Stanke4d579882016-04-22 13:28:46 -0400616 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700617 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700618}