blob: b40386d805db8e3a249d83c1d7f5ee601100a330 [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;
Brian Stanke7a81b532016-06-14 15:43:51 -040026import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070029import org.onosproject.incubator.net.tunnel.TunnelId;
Brian Stankefb61df42016-07-25 11:47:51 -040030import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070031import org.onosproject.incubator.net.virtual.NetworkId;
32import org.onosproject.incubator.net.virtual.TenantId;
33import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040034import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070035import org.onosproject.incubator.net.virtual.VirtualLink;
36import org.onosproject.incubator.net.virtual.VirtualNetwork;
37import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
38import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke11f6d532016-07-05 16:17:59 -040039import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070040import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070041import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
Thomas Vachuska858f65b2016-07-06 10:46:01 -070042import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070043import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070044import 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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070049import org.onosproject.net.ConnectPoint;
50import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040051import org.onosproject.net.HostId;
52import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040053import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070054import org.onosproject.net.PortNumber;
Brian Stanke86914282016-05-25 15:36:50 -040055import org.onosproject.net.device.DeviceService;
Claudine Chiu70222ad2016-11-17 22:29:20 -050056import org.onosproject.net.flow.FlowRuleService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040057import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040058import org.onosproject.net.intent.IntentEvent;
59import org.onosproject.net.intent.IntentListener;
60import org.onosproject.net.intent.IntentService;
61import org.onosproject.net.intent.IntentState;
Brian Stanke86914282016-05-25 15:36:50 -040062import org.onosproject.net.link.LinkService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070063import org.onosproject.net.provider.AbstractListenerProviderRegistry;
64import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000065import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040066import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070067import org.slf4j.Logger;
68import org.slf4j.LoggerFactory;
69
Brian Stanke86914282016-05-25 15:36:50 -040070import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070071import java.util.Set;
72
73import static com.google.common.base.Preconditions.checkNotNull;
74
75/**
76 * Implementation of the virtual network service.
77 */
78@Component(immediate = true)
79@Service
80public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080081 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
82 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
83 implements VirtualNetworkService, VirtualNetworkAdminService,
84 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070085
86 private final Logger log = LoggerFactory.getLogger(getClass());
87
88 private static final String TENANT_NULL = "Tenant ID cannot be null";
89 private static final String NETWORK_NULL = "Network ID cannot be null";
90 private static final String DEVICE_NULL = "Device ID cannot be null";
91 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected VirtualNetworkStore store;
95
Brian Stanke11f6d532016-07-05 16:17:59 -040096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected IntentService intentService;
98
yoonseon214963b2016-11-21 15:41:07 -080099 private final InternalVirtualIntentListener intentListener =
100 new InternalVirtualIntentListener();
Brian Stanke11f6d532016-07-05 16:17:59 -0400101
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500102 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700103
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700104 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700105
Brian Stanke11f6d532016-07-05 16:17:59 -0400106 /**
107 * Only used for Junit test methods outside of this package.
108 *
109 * @param store virtual network store
110 */
111 public void setStore(VirtualNetworkStore store) {
112 this.store = store;
113 }
114
115 /**
116 * Only used for Junit test methods outside of this package.
117 *
118 * @param intentService intent service
119 */
120
121 public void setIntentService(IntentService intentService) {
122 this.intentService = intentService;
123 }
124
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700125 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400126 public void activate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700127 store.setDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500128 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Brian Stanke11f6d532016-07-05 16:17:59 -0400129 intentService.addListener(intentListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700130 log.info("Started");
131 }
132
133 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400134 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700135 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500136 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Brian Stanke11f6d532016-07-05 16:17:59 -0400137 intentService.removeListener(intentListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700138 log.info("Stopped");
139 }
140
141 @Override
142 public void registerTenantId(TenantId tenantId) {
143 checkNotNull(tenantId, TENANT_NULL);
144 store.addTenantId(tenantId);
145 }
146
147 @Override
148 public void unregisterTenantId(TenantId tenantId) {
149 checkNotNull(tenantId, TENANT_NULL);
150 store.removeTenantId(tenantId);
151 }
152
153 @Override
154 public Set<TenantId> getTenantIds() {
155 return store.getTenantIds();
156 }
157
158 @Override
159 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
160 checkNotNull(tenantId, TENANT_NULL);
161 return store.addNetwork(tenantId);
162 }
163
164 @Override
165 public void removeVirtualNetwork(NetworkId networkId) {
166 checkNotNull(networkId, NETWORK_NULL);
167 store.removeNetwork(networkId);
168 }
169
170 @Override
171 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
172 checkNotNull(networkId, NETWORK_NULL);
173 checkNotNull(deviceId, DEVICE_NULL);
174 return store.addDevice(networkId, deviceId);
175 }
176
177 @Override
178 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
179 checkNotNull(networkId, NETWORK_NULL);
180 checkNotNull(deviceId, DEVICE_NULL);
181 store.removeDevice(networkId, deviceId);
182 }
183
184 @Override
yoonseon214963b2016-11-21 15:41:07 -0800185 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
186 MacAddress mac, VlanId vlan,
187 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400188 checkNotNull(networkId, NETWORK_NULL);
189 checkNotNull(hostId, DEVICE_NULL);
190 return store.addHost(networkId, hostId, mac, vlan, location, ips);
191 }
192
193 @Override
194 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
195 checkNotNull(networkId, NETWORK_NULL);
196 checkNotNull(hostId, DEVICE_NULL);
197 store.removeHost(networkId, hostId);
198 }
199
200 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700201 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400202 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700203 checkNotNull(networkId, NETWORK_NULL);
204 checkNotNull(src, LINK_POINT_NULL);
205 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400206 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
207 checkNotNull(physicalSrc, LINK_POINT_NULL);
208 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
209 checkNotNull(physicalDst, LINK_POINT_NULL);
210
211 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
212 Link.State state = Link.State.INACTIVE;
213 if (provider != null) {
214 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
215 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
216 }
217 return store.addLink(networkId, src, dst, state, null);
218 }
219
220 /**
221 * Maps the virtual connect point to a physical connect point.
222 *
223 * @param networkId network identifier
224 * @param virtualCp virtual connect point
225 * @return physical connect point
226 */
227 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
228 ConnectPoint virtualCp) {
229 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
230 for (VirtualPort port : ports) {
231 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700232 return new ConnectPoint(port.realizedBy().deviceId(),
233 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400234 }
235 }
236 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700237 }
238
Brian Stanke612cebf2016-05-02 10:21:33 -0400239 /**
240 * Maps the physical connect point to a virtual connect point.
241 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400242 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400243 * @param physicalCp physical connect point
244 * @return virtual connect point
245 */
246 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400247 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400248 Set<VirtualPort> ports = store.getPorts(networkId, null);
249 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700250 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
251 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400252 return new ConnectPoint(port.element().id(), port.number());
253 }
254 }
255 return null;
256 }
257
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700258 @Override
yoonseon214963b2016-11-21 15:41:07 -0800259 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
260 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700261 checkNotNull(networkId, NETWORK_NULL);
262 checkNotNull(src, LINK_POINT_NULL);
263 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400264 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700265 }
266
267 @Override
268 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700269 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700270 checkNotNull(networkId, NETWORK_NULL);
271 checkNotNull(deviceId, DEVICE_NULL);
272 checkNotNull(portNumber, "Port description cannot be null");
273 return store.addPort(networkId, deviceId, portNumber, realizedBy);
274 }
275
276 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700277 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
278 PortNumber portNumber, ConnectPoint realizedBy) {
279 checkNotNull(networkId, NETWORK_NULL);
280 checkNotNull(deviceId, DEVICE_NULL);
281 checkNotNull(portNumber, "Port description cannot be null");
282 checkNotNull(realizedBy, "Physical port description cannot be null");
283
284 store.bindPort(networkId, deviceId, portNumber, realizedBy);
285 }
286
287 @Override
yoonseon214963b2016-11-21 15:41:07 -0800288 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
289 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700290 checkNotNull(networkId, NETWORK_NULL);
291 checkNotNull(deviceId, DEVICE_NULL);
292 checkNotNull(portNumber, "Port number cannot be null");
293 store.removePort(networkId, deviceId, portNumber);
294 }
295
296 @Override
297 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
298 checkNotNull(tenantId, TENANT_NULL);
299 return store.getNetworks(tenantId);
300 }
301
Brian Stanke11f6d532016-07-05 16:17:59 -0400302 /**
303 * Returns the virtual network matching the network identifier.
304 *
305 * @param networkId network identifier
306 * @return virtual network
307 */
Brian Stanke86914282016-05-25 15:36:50 -0400308 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
309 checkNotNull(networkId, NETWORK_NULL);
310 return store.getNetwork(networkId);
311 }
312
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700313 @Override
314 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
315 checkNotNull(networkId, NETWORK_NULL);
316 return store.getDevices(networkId);
317 }
318
319 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400320 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
321 checkNotNull(networkId, NETWORK_NULL);
322 return store.getHosts(networkId);
323 }
324
325 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700326 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
327 checkNotNull(networkId, NETWORK_NULL);
328 return store.getLinks(networkId);
329 }
330
331 @Override
332 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
333 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700334 return store.getPorts(networkId, deviceId);
335 }
336
Brian Stanke86914282016-05-25 15:36:50 -0400337 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
338
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700339 @Override
340 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
341 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400342 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
343 VnetService service = lookup(serviceKey);
344 if (service == null) {
345 service = create(serviceKey);
346 }
347 return (T) service;
348 }
349
Brian Stanke11f6d532016-07-05 16:17:59 -0400350 /**
351 * Returns the Vnet service matching the service key.
352 *
353 * @param serviceKey service key
354 * @return vnet service
355 */
Brian Stanke86914282016-05-25 15:36:50 -0400356 private VnetService lookup(ServiceKey serviceKey) {
357 return networkServices.get(serviceKey);
358 }
359
Brian Stanke11f6d532016-07-05 16:17:59 -0400360 /**
361 * Creates a new service key using the specified network identifier and service class.
362 *
363 * @param networkId network identifier
364 * @param serviceClass service class
365 * @param <T> type of service
366 * @return service key
367 */
Brian Stanke86914282016-05-25 15:36:50 -0400368 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
369 return new ServiceKey(networkId, serviceClass);
370 }
371
372
Brian Stanke11f6d532016-07-05 16:17:59 -0400373 /**
374 * Create a new vnet service instance.
375 *
376 * @param serviceKey service key
377 * @return vnet service
378 */
Brian Stanke86914282016-05-25 15:36:50 -0400379 private VnetService create(ServiceKey serviceKey) {
380 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400381 checkNotNull(network, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400382 VnetService service;
383 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseon214963b2016-11-21 15:41:07 -0800384 service = new VirtualNetworkDeviceManager(this, network);
Brian Stanke86914282016-05-25 15:36:50 -0400385 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseon214963b2016-11-21 15:41:07 -0800386 service = new VirtualNetworkLinkManager(this, network);
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400387 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseon214963b2016-11-21 15:41:07 -0800388 service = new VirtualNetworkTopologyManager(this, network);
Brian Stanke11f6d532016-07-05 16:17:59 -0400389 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseon214963b2016-11-21 15:41:07 -0800390 service = new VirtualNetworkIntentManager(
391 this, network, new DefaultServiceDirectory());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400392 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseon214963b2016-11-21 15:41:07 -0800393 service = new VirtualNetworkHostManager(this, network);
Claudine Chiu45920dd2016-07-28 19:19:46 +0000394 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseon214963b2016-11-21 15:41:07 -0800395 service = new VirtualNetworkPathManager(this, network);
Claudine Chiu70222ad2016-11-17 22:29:20 -0500396 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
397 service = new VirtualNetworkFlowRuleManager(this, network);
Brian Stanke86914282016-05-25 15:36:50 -0400398 } else {
399 return null;
400 }
401 networkServices.put(serviceKey, service);
402 return service;
403 }
404
Brian Stanke11f6d532016-07-05 16:17:59 -0400405 /**
406 * Service key class.
407 */
Brian Stanke86914282016-05-25 15:36:50 -0400408 private class ServiceKey {
409 final NetworkId networkId;
410 final Class serviceClass;
411
Brian Stanke11f6d532016-07-05 16:17:59 -0400412 /**
413 * Constructor for service key.
414 *
415 * @param networkId network identifier
416 * @param serviceClass service class
417 */
Brian Stanke86914282016-05-25 15:36:50 -0400418 public ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800419
Brian Stanke86914282016-05-25 15:36:50 -0400420 checkNotNull(networkId, NETWORK_NULL);
421 this.networkId = networkId;
422 this.serviceClass = serviceClass;
423 }
424
Brian Stanke11f6d532016-07-05 16:17:59 -0400425 /**
426 * Returns the network identifier.
427 *
428 * @return network identifier
429 */
Brian Stanke86914282016-05-25 15:36:50 -0400430 public NetworkId networkId() {
431 return networkId;
432 }
433
Brian Stanke11f6d532016-07-05 16:17:59 -0400434 /**
435 * Returns the service class.
436 *
437 * @return service class
438 */
Brian Stanke86914282016-05-25 15:36:50 -0400439 public Class serviceClass() {
440 return serviceClass;
441 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700442 }
443
Brian Stanke11f6d532016-07-05 16:17:59 -0400444 /**
445 * Internal intent event listener.
446 */
447 private class InternalVirtualIntentListener implements IntentListener {
yoonseon214963b2016-11-21 15:41:07 -0800448
Brian Stanke11f6d532016-07-05 16:17:59 -0400449 @Override
450 public void event(IntentEvent event) {
451
452 // Ignore intent events that are not relevant.
453 if (!isRelevant(event)) {
454 return;
455 }
456
457 VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject();
458
459 switch (event.type()) {
460 case INSTALL_REQ:
461 store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ);
462 break;
463 case INSTALLED:
464 store.addOrUpdateIntent(intent, IntentState.INSTALLED);
465 break;
466 case WITHDRAW_REQ:
467 store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ);
468 break;
469 case WITHDRAWN:
470 store.addOrUpdateIntent(intent, IntentState.WITHDRAWN);
471 break;
472 case FAILED:
473 store.addOrUpdateIntent(intent, IntentState.FAILED);
474 break;
475 case CORRUPT:
476 store.addOrUpdateIntent(intent, IntentState.CORRUPT);
477 break;
478 case PURGED:
479 store.removeIntent(intent.key());
480 default:
481 break;
482 }
483 }
484
485 @Override
486 public boolean isRelevant(IntentEvent event) {
487 if (event.subject() instanceof VirtualNetworkIntent) {
488 return true;
489 }
490 return false;
491 }
492 }
493
494
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700495 @Override
yoonseon214963b2016-11-21 15:41:07 -0800496 protected VirtualNetworkProviderService
497 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700498 return new InternalVirtualNetworkProviderService(provider);
499 }
500
Brian Stankefb61df42016-07-25 11:47:51 -0400501 /**
502 * Service issued to registered virtual network providers so that they
503 * can interact with the core.
504 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700505 private class InternalVirtualNetworkProviderService
506 extends AbstractProviderService<VirtualNetworkProvider>
507 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400508 /**
509 * Constructor.
510 * @param provider virtual network provider
511 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700512 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
513 super(provider);
514 }
Brian Stanke4d579882016-04-22 13:28:46 -0400515
516 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400517 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400518 Set<TenantId> tenantIds = getTenantIds();
519 tenantIds.forEach(tenantId -> {
520 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
521
522 virtualNetworks.forEach(virtualNetwork -> {
523 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
524
525 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800526 if (isVirtualLinkInCluster(virtualNetwork.id(),
527 virtualLink, clusters)) {
528 store.updateLink(virtualLink, virtualLink.tunnelId(),
529 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400530 } else {
yoonseon214963b2016-11-21 15:41:07 -0800531 store.updateLink(virtualLink, virtualLink.tunnelId(),
532 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400533 }
534 });
535 });
536 });
537 }
538
539 /**
yoonseon214963b2016-11-21 15:41:07 -0800540 * Determines if the virtual link (both source and destination connect point)
541 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400542 *
543 * @param networkId virtual network identifier
544 * @param virtualLink virtual link
545 * @param clusters topology clusters
546 * @return true if the virtual link is in a cluster.
547 */
548 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
549 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800550 ConnectPoint srcPhysicalCp =
551 mapVirtualToPhysicalPort(networkId, virtualLink.src());
552 ConnectPoint dstPhysicalCp =
553 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400554
555 final boolean[] foundSrc = {false};
556 final boolean[] foundDst = {false};
557 clusters.forEach(connectPoints -> {
558 connectPoints.forEach(connectPoint -> {
559 if (connectPoint.equals(srcPhysicalCp)) {
560 foundSrc[0] = true;
561 } else if (connectPoint.equals(dstPhysicalCp)) {
562 foundDst[0] = true;
563 }
564 });
565 if (foundSrc[0] && foundDst[0]) {
566 return;
567 }
568 });
569 return foundSrc[0] && foundDst[0];
570 }
571
572 @Override
yoonseon214963b2016-11-21 15:41:07 -0800573 public void tunnelUp(NetworkId networkId, ConnectPoint src,
574 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400575 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
576 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
577 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
578 log.error("Src or dst virtual connection point was not found.");
579 }
580
581 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
582 if (virtualLink != null) {
583 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
584 }
Brian Stanke4d579882016-04-22 13:28:46 -0400585 }
586
587 @Override
yoonseon214963b2016-11-21 15:41:07 -0800588 public void tunnelDown(NetworkId networkId, ConnectPoint src,
589 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400590 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
591 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
592 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
593 log.error("Src or dst virtual connection point was not found.");
594 }
Brian Stanke4d579882016-04-22 13:28:46 -0400595
Brian Stanke612cebf2016-05-02 10:21:33 -0400596 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
597 if (virtualLink != null) {
598 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
599 }
Brian Stanke4d579882016-04-22 13:28:46 -0400600 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700601 }
602
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700603}