blob: 266564134cbce7a39c7a441a6225a844c4669226 [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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070030import org.onosproject.incubator.net.tunnel.TunnelId;
Brian Stankefb61df42016-07-25 11:47:51 -040031import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.virtual.NetworkId;
33import org.onosproject.incubator.net.virtual.TenantId;
34import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040035import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070036import org.onosproject.incubator.net.virtual.VirtualLink;
37import org.onosproject.incubator.net.virtual.VirtualNetwork;
38import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
39import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke11f6d532016-07-05 16:17:59 -040040import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070041import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
42import org.onosproject.incubator.net.virtual.VirtualNetworkService;
43import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
44import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
45import org.onosproject.incubator.net.virtual.VirtualPort;
yoonseon214963b2016-11-21 15:41:07 -080046import org.onosproject.incubator.net.virtual.VnetService;
yoonseon6b972c32016-12-06 16:45:03 -080047import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
48import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
49import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070050import org.onosproject.net.ConnectPoint;
51import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040052import org.onosproject.net.HostId;
53import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040054import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070055import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040056import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050057import org.onosproject.net.flow.FlowRuleService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040058import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040059import org.onosproject.net.intent.IntentEvent;
60import org.onosproject.net.intent.IntentListener;
61import org.onosproject.net.intent.IntentService;
62import org.onosproject.net.intent.IntentState;
Brian Stanke86914282016-05-25 15:36:50 -040063import org.onosproject.net.link.LinkService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070064import org.onosproject.net.provider.AbstractListenerProviderRegistry;
65import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000066import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040067import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070068import org.slf4j.Logger;
69import org.slf4j.LoggerFactory;
70
Brian Stanke86914282016-05-25 15:36:50 -040071import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072import java.util.Set;
73
74import static com.google.common.base.Preconditions.checkNotNull;
75
76/**
77 * Implementation of the virtual network service.
78 */
79@Component(immediate = true)
80@Service
81public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080082 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
83 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
84 implements VirtualNetworkService, VirtualNetworkAdminService,
85 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070086
87 private final Logger log = LoggerFactory.getLogger(getClass());
88
89 private static final String TENANT_NULL = "Tenant ID cannot be null";
90 private static final String NETWORK_NULL = "Network ID cannot be null";
91 private static final String DEVICE_NULL = "Device ID cannot be null";
92 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected VirtualNetworkStore store;
96
Brian Stanke11f6d532016-07-05 16:17:59 -040097 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected IntentService intentService;
99
yoonseon214963b2016-11-21 15:41:07 -0800100 private final InternalVirtualIntentListener intentListener =
101 new InternalVirtualIntentListener();
Brian Stanke11f6d532016-07-05 16:17:59 -0400102
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500103 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700104
yoonseonc6a69272017-01-12 18:22:20 -0800105 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
106
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700107 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700108
Brian Stanke11f6d532016-07-05 16:17:59 -0400109 /**
110 * Only used for Junit test methods outside of this package.
111 *
112 * @param store virtual network store
113 */
114 public void setStore(VirtualNetworkStore store) {
115 this.store = store;
116 }
117
118 /**
119 * Only used for Junit test methods outside of this package.
120 *
121 * @param intentService intent service
122 */
123
124 public void setIntentService(IntentService intentService) {
125 this.intentService = intentService;
126 }
127
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700128 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400129 public void activate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700130 store.setDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500131 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Brian Stanke11f6d532016-07-05 16:17:59 -0400132 intentService.addListener(intentListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700133 log.info("Started");
134 }
135
136 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400137 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700138 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500139 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Brian Stanke11f6d532016-07-05 16:17:59 -0400140 intentService.removeListener(intentListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700141 log.info("Stopped");
142 }
143
144 @Override
145 public void registerTenantId(TenantId tenantId) {
146 checkNotNull(tenantId, TENANT_NULL);
147 store.addTenantId(tenantId);
148 }
149
150 @Override
151 public void unregisterTenantId(TenantId tenantId) {
152 checkNotNull(tenantId, TENANT_NULL);
153 store.removeTenantId(tenantId);
154 }
155
156 @Override
157 public Set<TenantId> getTenantIds() {
158 return store.getTenantIds();
159 }
160
161 @Override
162 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
163 checkNotNull(tenantId, TENANT_NULL);
164 return store.addNetwork(tenantId);
165 }
166
167 @Override
168 public void removeVirtualNetwork(NetworkId networkId) {
169 checkNotNull(networkId, NETWORK_NULL);
170 store.removeNetwork(networkId);
171 }
172
173 @Override
174 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
175 checkNotNull(networkId, NETWORK_NULL);
176 checkNotNull(deviceId, DEVICE_NULL);
177 return store.addDevice(networkId, deviceId);
178 }
179
180 @Override
181 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
182 checkNotNull(networkId, NETWORK_NULL);
183 checkNotNull(deviceId, DEVICE_NULL);
184 store.removeDevice(networkId, deviceId);
185 }
186
187 @Override
yoonseon214963b2016-11-21 15:41:07 -0800188 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
189 MacAddress mac, VlanId vlan,
190 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400191 checkNotNull(networkId, NETWORK_NULL);
192 checkNotNull(hostId, DEVICE_NULL);
193 return store.addHost(networkId, hostId, mac, vlan, location, ips);
194 }
195
196 @Override
197 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
198 checkNotNull(networkId, NETWORK_NULL);
199 checkNotNull(hostId, DEVICE_NULL);
200 store.removeHost(networkId, hostId);
201 }
202
203 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700204 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400205 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700206 checkNotNull(networkId, NETWORK_NULL);
207 checkNotNull(src, LINK_POINT_NULL);
208 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400209 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
210 checkNotNull(physicalSrc, LINK_POINT_NULL);
211 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
212 checkNotNull(physicalDst, LINK_POINT_NULL);
213
214 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
215 Link.State state = Link.State.INACTIVE;
216 if (provider != null) {
217 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
218 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
219 }
220 return store.addLink(networkId, src, dst, state, null);
221 }
222
223 /**
224 * Maps the virtual connect point to a physical connect point.
225 *
226 * @param networkId network identifier
227 * @param virtualCp virtual connect point
228 * @return physical connect point
229 */
230 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
231 ConnectPoint virtualCp) {
232 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
233 for (VirtualPort port : ports) {
234 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700235 return new ConnectPoint(port.realizedBy().deviceId(),
236 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400237 }
238 }
239 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700240 }
241
Brian Stanke612cebf2016-05-02 10:21:33 -0400242 /**
243 * Maps the physical connect point to a virtual connect point.
244 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400245 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400246 * @param physicalCp physical connect point
247 * @return virtual connect point
248 */
249 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400250 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400251 Set<VirtualPort> ports = store.getPorts(networkId, null);
252 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700253 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
254 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400255 return new ConnectPoint(port.element().id(), port.number());
256 }
257 }
258 return null;
259 }
260
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700261 @Override
yoonseon214963b2016-11-21 15:41:07 -0800262 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
263 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700264 checkNotNull(networkId, NETWORK_NULL);
265 checkNotNull(src, LINK_POINT_NULL);
266 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400267 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700268 }
269
270 @Override
271 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700272 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700273 checkNotNull(networkId, NETWORK_NULL);
274 checkNotNull(deviceId, DEVICE_NULL);
275 checkNotNull(portNumber, "Port description cannot be null");
276 return store.addPort(networkId, deviceId, portNumber, realizedBy);
277 }
278
279 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700280 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
281 PortNumber portNumber, ConnectPoint realizedBy) {
282 checkNotNull(networkId, NETWORK_NULL);
283 checkNotNull(deviceId, DEVICE_NULL);
284 checkNotNull(portNumber, "Port description cannot be null");
285 checkNotNull(realizedBy, "Physical port description cannot be null");
286
287 store.bindPort(networkId, deviceId, portNumber, realizedBy);
288 }
289
290 @Override
yoonseon214963b2016-11-21 15:41:07 -0800291 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
292 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700293 checkNotNull(networkId, NETWORK_NULL);
294 checkNotNull(deviceId, DEVICE_NULL);
295 checkNotNull(portNumber, "Port number cannot be null");
296 store.removePort(networkId, deviceId, portNumber);
297 }
298
299 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800300 public ServiceDirectory getServiceDirectory() {
301 return serviceDirectory;
302 }
303
304 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700305 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
306 checkNotNull(tenantId, TENANT_NULL);
307 return store.getNetworks(tenantId);
308 }
309
Brian Stanke11f6d532016-07-05 16:17:59 -0400310 /**
311 * Returns the virtual network matching the network identifier.
312 *
313 * @param networkId network identifier
314 * @return virtual network
315 */
Brian Stanke86914282016-05-25 15:36:50 -0400316 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
317 checkNotNull(networkId, NETWORK_NULL);
318 return store.getNetwork(networkId);
319 }
320
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700321 @Override
322 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
323 checkNotNull(networkId, NETWORK_NULL);
324 return store.getDevices(networkId);
325 }
326
327 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400328 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
329 checkNotNull(networkId, NETWORK_NULL);
330 return store.getHosts(networkId);
331 }
332
333 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700334 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
335 checkNotNull(networkId, NETWORK_NULL);
336 return store.getLinks(networkId);
337 }
338
339 @Override
340 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
341 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700342 return store.getPorts(networkId, deviceId);
343 }
344
Brian Stanke86914282016-05-25 15:36:50 -0400345 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
346
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700347 @Override
348 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
349 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400350 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
351 VnetService service = lookup(serviceKey);
352 if (service == null) {
353 service = create(serviceKey);
354 }
355 return (T) service;
356 }
357
Brian Stanke11f6d532016-07-05 16:17:59 -0400358 /**
359 * Returns the Vnet service matching the service key.
360 *
361 * @param serviceKey service key
362 * @return vnet service
363 */
Brian Stanke86914282016-05-25 15:36:50 -0400364 private VnetService lookup(ServiceKey serviceKey) {
365 return networkServices.get(serviceKey);
366 }
367
Brian Stanke11f6d532016-07-05 16:17:59 -0400368 /**
369 * Creates a new service key using the specified network identifier and service class.
370 *
371 * @param networkId network identifier
372 * @param serviceClass service class
373 * @param <T> type of service
374 * @return service key
375 */
Brian Stanke86914282016-05-25 15:36:50 -0400376 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
377 return new ServiceKey(networkId, serviceClass);
378 }
379
380
Brian Stanke11f6d532016-07-05 16:17:59 -0400381 /**
382 * Create a new vnet service instance.
383 *
384 * @param serviceKey service key
385 * @return vnet service
386 */
Brian Stanke86914282016-05-25 15:36:50 -0400387 private VnetService create(ServiceKey serviceKey) {
388 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400389 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800390
Brian Stanke86914282016-05-25 15:36:50 -0400391 VnetService service;
392 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800393 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400394 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800395 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400396 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800397 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400398 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800399 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400400 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800401 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000402 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800403 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500404 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800405 service = new VirtualNetworkFlowRuleManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400406 } else {
407 return null;
408 }
409 networkServices.put(serviceKey, service);
410 return service;
411 }
412
Brian Stanke11f6d532016-07-05 16:17:59 -0400413 /**
414 * Service key class.
415 */
Brian Stanke86914282016-05-25 15:36:50 -0400416 private class ServiceKey {
417 final NetworkId networkId;
418 final Class serviceClass;
419
Brian Stanke11f6d532016-07-05 16:17:59 -0400420 /**
421 * Constructor for service key.
422 *
423 * @param networkId network identifier
424 * @param serviceClass service class
425 */
Brian Stanke86914282016-05-25 15:36:50 -0400426 public ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800427
Brian Stanke86914282016-05-25 15:36:50 -0400428 checkNotNull(networkId, NETWORK_NULL);
429 this.networkId = networkId;
430 this.serviceClass = serviceClass;
431 }
432
Brian Stanke11f6d532016-07-05 16:17:59 -0400433 /**
434 * Returns the network identifier.
435 *
436 * @return network identifier
437 */
Brian Stanke86914282016-05-25 15:36:50 -0400438 public NetworkId networkId() {
439 return networkId;
440 }
441
Brian Stanke11f6d532016-07-05 16:17:59 -0400442 /**
443 * Returns the service class.
444 *
445 * @return service class
446 */
Brian Stanke86914282016-05-25 15:36:50 -0400447 public Class serviceClass() {
448 return serviceClass;
449 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700450 }
451
Brian Stanke11f6d532016-07-05 16:17:59 -0400452 /**
453 * Internal intent event listener.
454 */
455 private class InternalVirtualIntentListener implements IntentListener {
yoonseon214963b2016-11-21 15:41:07 -0800456
Brian Stanke11f6d532016-07-05 16:17:59 -0400457 @Override
458 public void event(IntentEvent event) {
459
460 // Ignore intent events that are not relevant.
461 if (!isRelevant(event)) {
462 return;
463 }
464
465 VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject();
466
467 switch (event.type()) {
468 case INSTALL_REQ:
469 store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ);
470 break;
471 case INSTALLED:
472 store.addOrUpdateIntent(intent, IntentState.INSTALLED);
473 break;
474 case WITHDRAW_REQ:
475 store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ);
476 break;
477 case WITHDRAWN:
478 store.addOrUpdateIntent(intent, IntentState.WITHDRAWN);
479 break;
480 case FAILED:
481 store.addOrUpdateIntent(intent, IntentState.FAILED);
482 break;
483 case CORRUPT:
484 store.addOrUpdateIntent(intent, IntentState.CORRUPT);
485 break;
486 case PURGED:
487 store.removeIntent(intent.key());
488 default:
489 break;
490 }
491 }
492
493 @Override
494 public boolean isRelevant(IntentEvent event) {
495 if (event.subject() instanceof VirtualNetworkIntent) {
496 return true;
497 }
498 return false;
499 }
500 }
501
502
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700503 @Override
yoonseon214963b2016-11-21 15:41:07 -0800504 protected VirtualNetworkProviderService
505 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700506 return new InternalVirtualNetworkProviderService(provider);
507 }
508
yoonseon6b972c32016-12-06 16:45:03 -0800509
Brian Stankefb61df42016-07-25 11:47:51 -0400510 /**
511 * Service issued to registered virtual network providers so that they
512 * can interact with the core.
513 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700514 private class InternalVirtualNetworkProviderService
515 extends AbstractProviderService<VirtualNetworkProvider>
516 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400517 /**
518 * Constructor.
519 * @param provider virtual network provider
520 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700521 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
522 super(provider);
523 }
Brian Stanke4d579882016-04-22 13:28:46 -0400524
525 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400526 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400527 Set<TenantId> tenantIds = getTenantIds();
528 tenantIds.forEach(tenantId -> {
529 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
530
531 virtualNetworks.forEach(virtualNetwork -> {
532 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
533
534 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800535 if (isVirtualLinkInCluster(virtualNetwork.id(),
536 virtualLink, clusters)) {
537 store.updateLink(virtualLink, virtualLink.tunnelId(),
538 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400539 } else {
yoonseon214963b2016-11-21 15:41:07 -0800540 store.updateLink(virtualLink, virtualLink.tunnelId(),
541 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400542 }
543 });
544 });
545 });
546 }
547
548 /**
yoonseon214963b2016-11-21 15:41:07 -0800549 * Determines if the virtual link (both source and destination connect point)
550 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400551 *
552 * @param networkId virtual network identifier
553 * @param virtualLink virtual link
554 * @param clusters topology clusters
555 * @return true if the virtual link is in a cluster.
556 */
557 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
558 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800559 ConnectPoint srcPhysicalCp =
560 mapVirtualToPhysicalPort(networkId, virtualLink.src());
561 ConnectPoint dstPhysicalCp =
562 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400563
564 final boolean[] foundSrc = {false};
565 final boolean[] foundDst = {false};
566 clusters.forEach(connectPoints -> {
567 connectPoints.forEach(connectPoint -> {
568 if (connectPoint.equals(srcPhysicalCp)) {
569 foundSrc[0] = true;
570 } else if (connectPoint.equals(dstPhysicalCp)) {
571 foundDst[0] = true;
572 }
573 });
574 if (foundSrc[0] && foundDst[0]) {
575 return;
576 }
577 });
578 return foundSrc[0] && foundDst[0];
579 }
580
581 @Override
yoonseon214963b2016-11-21 15:41:07 -0800582 public void tunnelUp(NetworkId networkId, ConnectPoint src,
583 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400584 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
585 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
586 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
587 log.error("Src or dst virtual connection point was not found.");
588 }
589
590 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
591 if (virtualLink != null) {
592 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
593 }
Brian Stanke4d579882016-04-22 13:28:46 -0400594 }
595
596 @Override
yoonseon214963b2016-11-21 15:41:07 -0800597 public void tunnelDown(NetworkId networkId, ConnectPoint src,
598 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400599 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
600 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
601 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
602 log.error("Src or dst virtual connection point was not found.");
603 }
Brian Stanke4d579882016-04-22 13:28:46 -0400604
Brian Stanke612cebf2016-05-02 10:21:33 -0400605 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
606 if (virtualLink != null) {
607 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
608 }
Brian Stanke4d579882016-04-22 13:28:46 -0400609 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700610 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700611}