blob: 84589c80c43804b1f7611fab4a1b33c9585e3f79 [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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Brian Stanke11f6d532016-07-05 16:17:59 -040025import org.onlab.osgi.DefaultServiceDirectory;
yoonseonc6a69272017-01-12 18:22:20 -080026import org.onlab.osgi.ServiceDirectory;
Brian Stanke7a81b532016-06-14 15:43:51 -040027import org.onlab.packet.IpAddress;
28import org.onlab.packet.MacAddress;
29import org.onlab.packet.VlanId;
yoonseon322c9c32016-12-07 16:47:02 -080030import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.tunnel.TunnelId;
Brian Stankefb61df42016-07-25 11:47:51 -040033import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070034import org.onosproject.incubator.net.virtual.NetworkId;
35import org.onosproject.incubator.net.virtual.TenantId;
36import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040037import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070038import org.onosproject.incubator.net.virtual.VirtualLink;
39import org.onosproject.incubator.net.virtual.VirtualNetwork;
40import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
41import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke11f6d532016-07-05 16:17:59 -040042import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070043import 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;
yoonseon6b972c32016-12-06 16:45:03 -080049import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
50import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
51import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070052import org.onosproject.net.ConnectPoint;
53import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040054import org.onosproject.net.HostId;
55import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040056import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070057import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040058import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050059import org.onosproject.net.flow.FlowRuleService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040060import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040061import org.onosproject.net.intent.IntentEvent;
62import org.onosproject.net.intent.IntentListener;
63import org.onosproject.net.intent.IntentService;
64import org.onosproject.net.intent.IntentState;
Brian Stanke86914282016-05-25 15:36:50 -040065import org.onosproject.net.link.LinkService;
yoonseon322c9c32016-12-07 16:47:02 -080066import org.onosproject.net.packet.PacketService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070067import org.onosproject.net.provider.AbstractListenerProviderRegistry;
68import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000069import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040070import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070071import org.slf4j.Logger;
72import org.slf4j.LoggerFactory;
73
Brian Stanke86914282016-05-25 15:36:50 -040074import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070075import java.util.Set;
76
77import static com.google.common.base.Preconditions.checkNotNull;
78
79/**
80 * Implementation of the virtual network service.
81 */
82@Component(immediate = true)
83@Service
84public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080085 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
86 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
87 implements VirtualNetworkService, VirtualNetworkAdminService,
88 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070089
90 private final Logger log = LoggerFactory.getLogger(getClass());
91
92 private static final String TENANT_NULL = "Tenant ID cannot be null";
93 private static final String NETWORK_NULL = "Network ID cannot be null";
94 private static final String DEVICE_NULL = "Device ID cannot be null";
95 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
96
yoonseon322c9c32016-12-07 16:47:02 -080097 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
98 "org.onosproject.virtual-network";
99
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected VirtualNetworkStore store;
102
Brian Stanke11f6d532016-07-05 16:17:59 -0400103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected IntentService intentService;
105
yoonseon322c9c32016-12-07 16:47:02 -0800106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected CoreService coreService;
108
yoonseon214963b2016-11-21 15:41:07 -0800109 private final InternalVirtualIntentListener intentListener =
110 new InternalVirtualIntentListener();
Brian Stanke11f6d532016-07-05 16:17:59 -0400111
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() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700140 store.setDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500141 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Brian Stanke11f6d532016-07-05 16:17:59 -0400142 intentService.addListener(intentListener);
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);
Brian Stanke11f6d532016-07-05 16:17:59 -0400151 intentService.removeListener(intentListener);
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
Brian Stanke86914282016-05-25 15:36:50 -0400356 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
357
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700358 @Override
359 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
360 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400361 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
362 VnetService service = lookup(serviceKey);
363 if (service == null) {
364 service = create(serviceKey);
365 }
366 return (T) service;
367 }
368
yoonseon322c9c32016-12-07 16:47:02 -0800369 @Override
370 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
371 return appId;
372 }
373
Brian Stanke11f6d532016-07-05 16:17:59 -0400374 /**
375 * Returns the Vnet service matching the service key.
376 *
377 * @param serviceKey service key
378 * @return vnet service
379 */
Brian Stanke86914282016-05-25 15:36:50 -0400380 private VnetService lookup(ServiceKey serviceKey) {
381 return networkServices.get(serviceKey);
382 }
383
Brian Stanke11f6d532016-07-05 16:17:59 -0400384 /**
385 * Creates a new service key using the specified network identifier and service class.
386 *
387 * @param networkId network identifier
388 * @param serviceClass service class
389 * @param <T> type of service
390 * @return service key
391 */
Brian Stanke86914282016-05-25 15:36:50 -0400392 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
393 return new ServiceKey(networkId, serviceClass);
394 }
395
396
Brian Stanke11f6d532016-07-05 16:17:59 -0400397 /**
398 * Create a new vnet service instance.
399 *
400 * @param serviceKey service key
401 * @return vnet service
402 */
Brian Stanke86914282016-05-25 15:36:50 -0400403 private VnetService create(ServiceKey serviceKey) {
404 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400405 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800406
Brian Stanke86914282016-05-25 15:36:50 -0400407 VnetService service;
408 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800409 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400410 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800411 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400412 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800413 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400414 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800415 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400416 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800417 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000418 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800419 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500420 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800421 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800422 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
423 service = new VirtualNetworkPacketManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400424 } else {
425 return null;
426 }
427 networkServices.put(serviceKey, service);
428 return service;
429 }
430
Brian Stanke11f6d532016-07-05 16:17:59 -0400431 /**
432 * Service key class.
433 */
Brian Stanke86914282016-05-25 15:36:50 -0400434 private class ServiceKey {
435 final NetworkId networkId;
436 final Class serviceClass;
437
Brian Stanke11f6d532016-07-05 16:17:59 -0400438 /**
439 * Constructor for service key.
440 *
441 * @param networkId network identifier
442 * @param serviceClass service class
443 */
Brian Stanke86914282016-05-25 15:36:50 -0400444 public ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800445
Brian Stanke86914282016-05-25 15:36:50 -0400446 checkNotNull(networkId, NETWORK_NULL);
447 this.networkId = networkId;
448 this.serviceClass = serviceClass;
449 }
450
Brian Stanke11f6d532016-07-05 16:17:59 -0400451 /**
452 * Returns the network identifier.
453 *
454 * @return network identifier
455 */
Brian Stanke86914282016-05-25 15:36:50 -0400456 public NetworkId networkId() {
457 return networkId;
458 }
459
Brian Stanke11f6d532016-07-05 16:17:59 -0400460 /**
461 * Returns the service class.
462 *
463 * @return service class
464 */
Brian Stanke86914282016-05-25 15:36:50 -0400465 public Class serviceClass() {
466 return serviceClass;
467 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700468 }
469
Brian Stanke11f6d532016-07-05 16:17:59 -0400470 /**
471 * Internal intent event listener.
472 */
473 private class InternalVirtualIntentListener implements IntentListener {
yoonseon214963b2016-11-21 15:41:07 -0800474
Brian Stanke11f6d532016-07-05 16:17:59 -0400475 @Override
476 public void event(IntentEvent event) {
477
478 // Ignore intent events that are not relevant.
479 if (!isRelevant(event)) {
480 return;
481 }
482
483 VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject();
484
485 switch (event.type()) {
486 case INSTALL_REQ:
487 store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ);
488 break;
489 case INSTALLED:
490 store.addOrUpdateIntent(intent, IntentState.INSTALLED);
491 break;
492 case WITHDRAW_REQ:
493 store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ);
494 break;
495 case WITHDRAWN:
496 store.addOrUpdateIntent(intent, IntentState.WITHDRAWN);
497 break;
498 case FAILED:
499 store.addOrUpdateIntent(intent, IntentState.FAILED);
500 break;
501 case CORRUPT:
502 store.addOrUpdateIntent(intent, IntentState.CORRUPT);
503 break;
504 case PURGED:
505 store.removeIntent(intent.key());
506 default:
507 break;
508 }
509 }
510
511 @Override
512 public boolean isRelevant(IntentEvent event) {
513 if (event.subject() instanceof VirtualNetworkIntent) {
514 return true;
515 }
516 return false;
517 }
518 }
519
520
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700521 @Override
yoonseon214963b2016-11-21 15:41:07 -0800522 protected VirtualNetworkProviderService
523 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700524 return new InternalVirtualNetworkProviderService(provider);
525 }
526
yoonseon6b972c32016-12-06 16:45:03 -0800527
Brian Stankefb61df42016-07-25 11:47:51 -0400528 /**
529 * Service issued to registered virtual network providers so that they
530 * can interact with the core.
531 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700532 private class InternalVirtualNetworkProviderService
533 extends AbstractProviderService<VirtualNetworkProvider>
534 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400535 /**
536 * Constructor.
537 * @param provider virtual network provider
538 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700539 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
540 super(provider);
541 }
Brian Stanke4d579882016-04-22 13:28:46 -0400542
543 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400544 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400545 Set<TenantId> tenantIds = getTenantIds();
546 tenantIds.forEach(tenantId -> {
547 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
548
549 virtualNetworks.forEach(virtualNetwork -> {
550 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
551
552 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800553 if (isVirtualLinkInCluster(virtualNetwork.id(),
554 virtualLink, clusters)) {
555 store.updateLink(virtualLink, virtualLink.tunnelId(),
556 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400557 } else {
yoonseon214963b2016-11-21 15:41:07 -0800558 store.updateLink(virtualLink, virtualLink.tunnelId(),
559 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400560 }
561 });
562 });
563 });
564 }
565
566 /**
yoonseon214963b2016-11-21 15:41:07 -0800567 * Determines if the virtual link (both source and destination connect point)
568 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400569 *
570 * @param networkId virtual network identifier
571 * @param virtualLink virtual link
572 * @param clusters topology clusters
573 * @return true if the virtual link is in a cluster.
574 */
575 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
576 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800577 ConnectPoint srcPhysicalCp =
578 mapVirtualToPhysicalPort(networkId, virtualLink.src());
579 ConnectPoint dstPhysicalCp =
580 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400581
582 final boolean[] foundSrc = {false};
583 final boolean[] foundDst = {false};
584 clusters.forEach(connectPoints -> {
585 connectPoints.forEach(connectPoint -> {
586 if (connectPoint.equals(srcPhysicalCp)) {
587 foundSrc[0] = true;
588 } else if (connectPoint.equals(dstPhysicalCp)) {
589 foundDst[0] = true;
590 }
591 });
592 if (foundSrc[0] && foundDst[0]) {
593 return;
594 }
595 });
596 return foundSrc[0] && foundDst[0];
597 }
598
599 @Override
yoonseon214963b2016-11-21 15:41:07 -0800600 public void tunnelUp(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 }
607
608 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
609 if (virtualLink != null) {
610 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
611 }
Brian Stanke4d579882016-04-22 13:28:46 -0400612 }
613
614 @Override
yoonseon214963b2016-11-21 15:41:07 -0800615 public void tunnelDown(NetworkId networkId, ConnectPoint src,
616 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400617 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
618 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
619 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
620 log.error("Src or dst virtual connection point was not found.");
621 }
Brian Stanke4d579882016-04-22 13:28:46 -0400622
Brian Stanke612cebf2016-05-02 10:21:33 -0400623 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
624 if (virtualLink != null) {
625 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
626 }
Brian Stanke4d579882016-04-22 13:28:46 -0400627 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700628 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700629}