blob: 34084dc32b1061ace1b606b76c4634e63206f621 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connorce2a03d2017-08-03 19:21:03 -07002 * Copyright 2015-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
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;
Brian Stanke11f6d532016-07-05 16:17:59 -040043import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070044import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
45import org.onosproject.incubator.net.virtual.VirtualNetworkService;
46import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
47import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
48import org.onosproject.incubator.net.virtual.VirtualPort;
yoonseon214963b2016-11-21 15:41:07 -080049import org.onosproject.incubator.net.virtual.VnetService;
Claudine Chiu465a2602017-03-17 18:33:36 -040050import org.onosproject.incubator.net.virtual.event.VirtualEvent;
51import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
yoonseon6b972c32016-12-06 16:45:03 -080052import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
53import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
54import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070055import org.onosproject.net.ConnectPoint;
56import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040057import org.onosproject.net.HostId;
58import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040059import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070060import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040061import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050062import org.onosproject.net.flow.FlowRuleService;
yoonseon86bebed2017-02-03 15:23:57 -080063import org.onosproject.net.flowobjective.FlowObjectiveService;
Claudine Chiu465a2602017-03-17 18:33:36 -040064import org.onosproject.net.group.GroupService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040065import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040066import org.onosproject.net.intent.IntentEvent;
67import org.onosproject.net.intent.IntentListener;
68import org.onosproject.net.intent.IntentService;
69import org.onosproject.net.intent.IntentState;
Brian Stanke86914282016-05-25 15:36:50 -040070import org.onosproject.net.link.LinkService;
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
Brian Stanke86914282016-05-25 15:36:50 -040079import java.util.Map;
Claudine Chiue7f6b912017-02-24 14:13:30 -050080import java.util.Objects;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070081import java.util.Set;
82
83import static com.google.common.base.Preconditions.checkNotNull;
84
85/**
86 * Implementation of the virtual network service.
87 */
88@Component(immediate = true)
89@Service
90public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080091 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
92 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
93 implements VirtualNetworkService, VirtualNetworkAdminService,
94 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070095
96 private final Logger log = LoggerFactory.getLogger(getClass());
97
98 private static final String TENANT_NULL = "Tenant ID cannot be null";
99 private static final String NETWORK_NULL = "Network ID cannot be null";
100 private static final String DEVICE_NULL = "Device ID cannot be null";
101 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
102
yoonseon322c9c32016-12-07 16:47:02 -0800103 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
104 "org.onosproject.virtual-network";
105
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected VirtualNetworkStore store;
108
Brian Stanke11f6d532016-07-05 16:17:59 -0400109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected IntentService intentService;
111
yoonseon322c9c32016-12-07 16:47:02 -0800112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected CoreService coreService;
114
yoonseon214963b2016-11-21 15:41:07 -0800115 private final InternalVirtualIntentListener intentListener =
116 new InternalVirtualIntentListener();
Brian Stanke11f6d532016-07-05 16:17:59 -0400117
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500118 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700119
yoonseonc6a69272017-01-12 18:22:20 -0800120 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
yoonseon322c9c32016-12-07 16:47:02 -0800121 private ApplicationId appId;
yoonseonc6a69272017-01-12 18:22:20 -0800122
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700123 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700124
Brian Stanke11f6d532016-07-05 16:17:59 -0400125 /**
126 * Only used for Junit test methods outside of this package.
127 *
128 * @param store virtual network store
129 */
130 public void setStore(VirtualNetworkStore store) {
131 this.store = store;
132 }
133
134 /**
135 * Only used for Junit test methods outside of this package.
136 *
137 * @param intentService intent service
138 */
139
140 public void setIntentService(IntentService intentService) {
141 this.intentService = intentService;
142 }
143
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700144 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400145 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500146 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Claudine Chiu465a2602017-03-17 18:33:36 -0400147 eventDispatcher.addSink(VirtualEvent.class,
148 VirtualListenerRegistryManager.getInstance());
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900149 store.setDelegate(delegate);
Brian Stanke11f6d532016-07-05 16:17:59 -0400150 intentService.addListener(intentListener);
yoonseon322c9c32016-12-07 16:47:02 -0800151 appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700152 log.info("Started");
153 }
154
155 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400156 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700157 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500158 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Claudine Chiu465a2602017-03-17 18:33:36 -0400159 eventDispatcher.removeSink(VirtualEvent.class);
Brian Stanke11f6d532016-07-05 16:17:59 -0400160 intentService.removeListener(intentListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700161 log.info("Stopped");
162 }
163
164 @Override
165 public void registerTenantId(TenantId tenantId) {
166 checkNotNull(tenantId, TENANT_NULL);
167 store.addTenantId(tenantId);
168 }
169
170 @Override
171 public void unregisterTenantId(TenantId tenantId) {
172 checkNotNull(tenantId, TENANT_NULL);
173 store.removeTenantId(tenantId);
174 }
175
176 @Override
177 public Set<TenantId> getTenantIds() {
178 return store.getTenantIds();
179 }
180
181 @Override
182 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
183 checkNotNull(tenantId, TENANT_NULL);
184 return store.addNetwork(tenantId);
185 }
186
187 @Override
188 public void removeVirtualNetwork(NetworkId networkId) {
189 checkNotNull(networkId, NETWORK_NULL);
190 store.removeNetwork(networkId);
191 }
192
193 @Override
194 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
195 checkNotNull(networkId, NETWORK_NULL);
196 checkNotNull(deviceId, DEVICE_NULL);
197 return store.addDevice(networkId, deviceId);
198 }
199
200 @Override
201 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
202 checkNotNull(networkId, NETWORK_NULL);
203 checkNotNull(deviceId, DEVICE_NULL);
204 store.removeDevice(networkId, deviceId);
205 }
206
207 @Override
yoonseon214963b2016-11-21 15:41:07 -0800208 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
209 MacAddress mac, VlanId vlan,
210 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400211 checkNotNull(networkId, NETWORK_NULL);
212 checkNotNull(hostId, DEVICE_NULL);
213 return store.addHost(networkId, hostId, mac, vlan, location, ips);
214 }
215
216 @Override
217 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
218 checkNotNull(networkId, NETWORK_NULL);
219 checkNotNull(hostId, DEVICE_NULL);
220 store.removeHost(networkId, hostId);
221 }
222
223 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700224 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400225 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700226 checkNotNull(networkId, NETWORK_NULL);
227 checkNotNull(src, LINK_POINT_NULL);
228 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400229 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
230 checkNotNull(physicalSrc, LINK_POINT_NULL);
231 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
232 checkNotNull(physicalDst, LINK_POINT_NULL);
233
234 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
235 Link.State state = Link.State.INACTIVE;
236 if (provider != null) {
237 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
238 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
239 }
240 return store.addLink(networkId, src, dst, state, null);
241 }
242
243 /**
244 * Maps the virtual connect point to a physical connect point.
245 *
246 * @param networkId network identifier
247 * @param virtualCp virtual connect point
248 * @return physical connect point
249 */
250 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
251 ConnectPoint virtualCp) {
252 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
253 for (VirtualPort port : ports) {
254 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700255 return new ConnectPoint(port.realizedBy().deviceId(),
256 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400257 }
258 }
259 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700260 }
261
Brian Stanke612cebf2016-05-02 10:21:33 -0400262 /**
263 * Maps the physical connect point to a virtual connect point.
264 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400265 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400266 * @param physicalCp physical connect point
267 * @return virtual connect point
268 */
269 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400270 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400271 Set<VirtualPort> ports = store.getPorts(networkId, null);
272 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700273 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
274 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400275 return new ConnectPoint(port.element().id(), port.number());
276 }
277 }
278 return null;
279 }
280
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700281 @Override
yoonseon214963b2016-11-21 15:41:07 -0800282 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
283 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700284 checkNotNull(networkId, NETWORK_NULL);
285 checkNotNull(src, LINK_POINT_NULL);
286 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400287 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700288 }
289
290 @Override
291 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700292 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700293 checkNotNull(networkId, NETWORK_NULL);
294 checkNotNull(deviceId, DEVICE_NULL);
295 checkNotNull(portNumber, "Port description cannot be null");
296 return store.addPort(networkId, deviceId, portNumber, realizedBy);
297 }
298
299 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700300 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
301 PortNumber portNumber, ConnectPoint realizedBy) {
302 checkNotNull(networkId, NETWORK_NULL);
303 checkNotNull(deviceId, DEVICE_NULL);
304 checkNotNull(portNumber, "Port description cannot be null");
305 checkNotNull(realizedBy, "Physical port description cannot be null");
306
307 store.bindPort(networkId, deviceId, portNumber, realizedBy);
308 }
309
310 @Override
yoonseon214963b2016-11-21 15:41:07 -0800311 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
312 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700313 checkNotNull(networkId, NETWORK_NULL);
314 checkNotNull(deviceId, DEVICE_NULL);
315 checkNotNull(portNumber, "Port number cannot be null");
316 store.removePort(networkId, deviceId, portNumber);
317 }
318
319 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800320 public ServiceDirectory getServiceDirectory() {
321 return serviceDirectory;
322 }
323
324 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700325 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
326 checkNotNull(tenantId, TENANT_NULL);
327 return store.getNetworks(tenantId);
328 }
329
Brian Stanke11f6d532016-07-05 16:17:59 -0400330 /**
331 * Returns the virtual network matching the network identifier.
332 *
333 * @param networkId network identifier
334 * @return virtual network
335 */
Brian Stanke86914282016-05-25 15:36:50 -0400336 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
337 checkNotNull(networkId, NETWORK_NULL);
338 return store.getNetwork(networkId);
339 }
340
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700341 @Override
342 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
343 checkNotNull(networkId, NETWORK_NULL);
344 return store.getDevices(networkId);
345 }
346
347 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400348 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
349 checkNotNull(networkId, NETWORK_NULL);
350 return store.getHosts(networkId);
351 }
352
353 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700354 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
355 checkNotNull(networkId, NETWORK_NULL);
356 return store.getLinks(networkId);
357 }
358
359 @Override
360 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
361 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700362 return store.getPorts(networkId, deviceId);
363 }
364
Yoonseon Hanffcc32f2017-05-03 14:42:17 -0700365 @Override
366 public Set<DeviceId> getPhysicalDevices(NetworkId networkId,
367 VirtualDevice virtualDevice) {
368 checkNotNull(networkId, "Network ID cannot be null");
369 checkNotNull(virtualDevice, "Virtual device cannot be null");
370 Set<VirtualPort> virtualPortSet =
371 getVirtualPorts(networkId, virtualDevice.id());
372 Set<DeviceId> physicalDeviceSet = Sets.newConcurrentHashSet();
373
374 virtualPortSet.forEach(virtualPort -> {
375 if (virtualPort.realizedBy() != null) {
376 physicalDeviceSet.add(virtualPort.realizedBy().deviceId());
377 }
378 });
379
380 return physicalDeviceSet;
381 }
382
Brian Stanke86914282016-05-25 15:36:50 -0400383 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
384
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700385 @Override
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900386 @SuppressWarnings("unchecked")
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700387 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
388 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400389 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
390 VnetService service = lookup(serviceKey);
391 if (service == null) {
392 service = create(serviceKey);
393 }
394 return (T) service;
395 }
396
yoonseon322c9c32016-12-07 16:47:02 -0800397 @Override
398 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
399 return appId;
400 }
401
Brian Stanke11f6d532016-07-05 16:17:59 -0400402 /**
403 * Returns the Vnet service matching the service key.
404 *
405 * @param serviceKey service key
406 * @return vnet service
407 */
Brian Stanke86914282016-05-25 15:36:50 -0400408 private VnetService lookup(ServiceKey serviceKey) {
409 return networkServices.get(serviceKey);
410 }
411
Brian Stanke11f6d532016-07-05 16:17:59 -0400412 /**
413 * Creates a new service key using the specified network identifier and service class.
414 *
415 * @param networkId network identifier
416 * @param serviceClass service class
417 * @param <T> type of service
418 * @return service key
419 */
Brian Stanke86914282016-05-25 15:36:50 -0400420 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
421 return new ServiceKey(networkId, serviceClass);
422 }
423
424
Brian Stanke11f6d532016-07-05 16:17:59 -0400425 /**
426 * Create a new vnet service instance.
427 *
428 * @param serviceKey service key
429 * @return vnet service
430 */
Brian Stanke86914282016-05-25 15:36:50 -0400431 private VnetService create(ServiceKey serviceKey) {
432 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400433 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800434
Brian Stanke86914282016-05-25 15:36:50 -0400435 VnetService service;
436 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800437 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400438 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800439 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400440 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800441 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400442 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800443 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400444 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800445 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000446 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800447 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500448 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800449 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800450 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
451 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800452 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
453 service = new VirtualNetworkGroupManager(this, network.id());
yoonseon86bebed2017-02-03 15:23:57 -0800454 } else if (serviceKey.serviceClass.equals(FlowObjectiveService.class)) {
455 service = new VirtualNetworkFlowObjectiveManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400456 } else {
457 return null;
458 }
459 networkServices.put(serviceKey, service);
460 return service;
461 }
462
Brian Stanke11f6d532016-07-05 16:17:59 -0400463 /**
464 * Service key class.
465 */
Claudine Chiu9a18f492017-02-27 15:57:06 -0500466 private static class ServiceKey {
Brian Stanke86914282016-05-25 15:36:50 -0400467 final NetworkId networkId;
468 final Class serviceClass;
469
Brian Stanke11f6d532016-07-05 16:17:59 -0400470 /**
471 * Constructor for service key.
472 *
473 * @param networkId network identifier
474 * @param serviceClass service class
475 */
Yoonseon Hanb14461b2017-03-07 14:08:01 +0900476 ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800477
Brian Stanke86914282016-05-25 15:36:50 -0400478 checkNotNull(networkId, NETWORK_NULL);
479 this.networkId = networkId;
480 this.serviceClass = serviceClass;
481 }
482
Brian Stanke11f6d532016-07-05 16:17:59 -0400483 /**
484 * Returns the network identifier.
485 *
486 * @return network identifier
487 */
Brian Stanke86914282016-05-25 15:36:50 -0400488 public NetworkId networkId() {
489 return networkId;
490 }
491
Brian Stanke11f6d532016-07-05 16:17:59 -0400492 /**
493 * Returns the service class.
494 *
495 * @return service class
496 */
Brian Stanke86914282016-05-25 15:36:50 -0400497 public Class serviceClass() {
498 return serviceClass;
499 }
Claudine Chiue7f6b912017-02-24 14:13:30 -0500500
501 @Override
502 public int hashCode() {
503 return Objects.hash(networkId, serviceClass);
504 }
505
506 @Override
507 public boolean equals(Object obj) {
508 if (this == obj) {
509 return true;
510 }
511 if (obj instanceof ServiceKey) {
512 ServiceKey that = (ServiceKey) obj;
513 return Objects.equals(this.networkId, that.networkId) &&
514 Objects.equals(this.serviceClass, that.serviceClass);
515 }
516 return false;
517 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700518 }
519
Brian Stanke11f6d532016-07-05 16:17:59 -0400520 /**
521 * Internal intent event listener.
522 */
523 private class InternalVirtualIntentListener implements IntentListener {
yoonseon214963b2016-11-21 15:41:07 -0800524
Brian Stanke11f6d532016-07-05 16:17:59 -0400525 @Override
526 public void event(IntentEvent event) {
527
528 // Ignore intent events that are not relevant.
529 if (!isRelevant(event)) {
530 return;
531 }
532
533 VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject();
534
535 switch (event.type()) {
536 case INSTALL_REQ:
537 store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ);
538 break;
539 case INSTALLED:
540 store.addOrUpdateIntent(intent, IntentState.INSTALLED);
541 break;
542 case WITHDRAW_REQ:
543 store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ);
544 break;
545 case WITHDRAWN:
546 store.addOrUpdateIntent(intent, IntentState.WITHDRAWN);
547 break;
548 case FAILED:
549 store.addOrUpdateIntent(intent, IntentState.FAILED);
550 break;
551 case CORRUPT:
552 store.addOrUpdateIntent(intent, IntentState.CORRUPT);
553 break;
554 case PURGED:
555 store.removeIntent(intent.key());
556 default:
557 break;
558 }
559 }
560
561 @Override
562 public boolean isRelevant(IntentEvent event) {
563 if (event.subject() instanceof VirtualNetworkIntent) {
564 return true;
565 }
566 return false;
567 }
568 }
569
570
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700571 @Override
yoonseon214963b2016-11-21 15:41:07 -0800572 protected VirtualNetworkProviderService
573 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700574 return new InternalVirtualNetworkProviderService(provider);
575 }
576
yoonseon6b972c32016-12-06 16:45:03 -0800577
Brian Stankefb61df42016-07-25 11:47:51 -0400578 /**
579 * Service issued to registered virtual network providers so that they
580 * can interact with the core.
581 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700582 private class InternalVirtualNetworkProviderService
583 extends AbstractProviderService<VirtualNetworkProvider>
584 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400585 /**
586 * Constructor.
587 * @param provider virtual network provider
588 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700589 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
590 super(provider);
591 }
Brian Stanke4d579882016-04-22 13:28:46 -0400592
593 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400594 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400595 Set<TenantId> tenantIds = getTenantIds();
596 tenantIds.forEach(tenantId -> {
597 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
598
599 virtualNetworks.forEach(virtualNetwork -> {
600 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
601
602 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800603 if (isVirtualLinkInCluster(virtualNetwork.id(),
604 virtualLink, clusters)) {
605 store.updateLink(virtualLink, virtualLink.tunnelId(),
606 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400607 } else {
yoonseon214963b2016-11-21 15:41:07 -0800608 store.updateLink(virtualLink, virtualLink.tunnelId(),
609 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400610 }
611 });
612 });
613 });
614 }
615
616 /**
yoonseon214963b2016-11-21 15:41:07 -0800617 * Determines if the virtual link (both source and destination connect point)
618 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400619 *
620 * @param networkId virtual network identifier
621 * @param virtualLink virtual link
622 * @param clusters topology clusters
623 * @return true if the virtual link is in a cluster.
624 */
625 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
626 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800627 ConnectPoint srcPhysicalCp =
628 mapVirtualToPhysicalPort(networkId, virtualLink.src());
629 ConnectPoint dstPhysicalCp =
630 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400631
632 final boolean[] foundSrc = {false};
633 final boolean[] foundDst = {false};
634 clusters.forEach(connectPoints -> {
635 connectPoints.forEach(connectPoint -> {
636 if (connectPoint.equals(srcPhysicalCp)) {
637 foundSrc[0] = true;
638 } else if (connectPoint.equals(dstPhysicalCp)) {
639 foundDst[0] = true;
640 }
641 });
642 if (foundSrc[0] && foundDst[0]) {
643 return;
644 }
645 });
646 return foundSrc[0] && foundDst[0];
647 }
648
649 @Override
yoonseon214963b2016-11-21 15:41:07 -0800650 public void tunnelUp(NetworkId networkId, ConnectPoint src,
651 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400652 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
653 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
654 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
655 log.error("Src or dst virtual connection point was not found.");
656 }
657
658 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
659 if (virtualLink != null) {
660 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
661 }
Brian Stanke4d579882016-04-22 13:28:46 -0400662 }
663
664 @Override
yoonseon214963b2016-11-21 15:41:07 -0800665 public void tunnelDown(NetworkId networkId, ConnectPoint src,
666 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400667 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
668 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
669 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
670 log.error("Src or dst virtual connection point was not found.");
671 }
Brian Stanke4d579882016-04-22 13:28:46 -0400672
Brian Stanke612cebf2016-05-02 10:21:33 -0400673 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
674 if (virtualLink != null) {
675 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
676 }
Brian Stanke4d579882016-04-22 13:28:46 -0400677 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700678 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700679}