blob: e9ce122de74fe46a868f102d07c1581a37cef19f [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;
yoonseondc3210d2017-01-25 16:03:10 -080060import org.onosproject.net.group.GroupService;
Claudine Chiu30a8a2a2016-07-14 17:09:04 -040061import org.onosproject.net.host.HostService;
Brian Stanke11f6d532016-07-05 16:17:59 -040062import org.onosproject.net.intent.IntentEvent;
63import org.onosproject.net.intent.IntentListener;
64import org.onosproject.net.intent.IntentService;
65import org.onosproject.net.intent.IntentState;
Brian Stanke86914282016-05-25 15:36:50 -040066import org.onosproject.net.link.LinkService;
yoonseon322c9c32016-12-07 16:47:02 -080067import org.onosproject.net.packet.PacketService;
Thomas Vachuska3d62fd72015-09-25 14:58:13 -070068import org.onosproject.net.provider.AbstractListenerProviderRegistry;
69import org.onosproject.net.provider.AbstractProviderService;
Claudine Chiu45920dd2016-07-28 19:19:46 +000070import org.onosproject.net.topology.PathService;
Brian Stanke8e9f8d12016-06-08 14:48:33 -040071import org.onosproject.net.topology.TopologyService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
Brian Stanke86914282016-05-25 15:36:50 -040075import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070076import java.util.Set;
77
78import static com.google.common.base.Preconditions.checkNotNull;
79
80/**
81 * Implementation of the virtual network service.
82 */
83@Component(immediate = true)
84@Service
85public class VirtualNetworkManager
yoonseon214963b2016-11-21 15:41:07 -080086 extends AbstractListenerProviderRegistry<VirtualNetworkEvent,
87 VirtualNetworkListener, VirtualNetworkProvider, VirtualNetworkProviderService>
88 implements VirtualNetworkService, VirtualNetworkAdminService,
89 VirtualNetworkProviderRegistry {
Thomas Vachuska33979fd2015-07-31 11:41:14 -070090
91 private final Logger log = LoggerFactory.getLogger(getClass());
92
93 private static final String TENANT_NULL = "Tenant ID cannot be null";
94 private static final String NETWORK_NULL = "Network ID cannot be null";
95 private static final String DEVICE_NULL = "Device ID cannot be null";
96 private static final String LINK_POINT_NULL = "Link end-point cannot be null";
97
yoonseon322c9c32016-12-07 16:47:02 -080098 private static final String VIRTUAL_NETWORK_APP_ID_STRING =
99 "org.onosproject.virtual-network";
100
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected VirtualNetworkStore store;
103
Brian Stanke11f6d532016-07-05 16:17:59 -0400104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected IntentService intentService;
106
yoonseon322c9c32016-12-07 16:47:02 -0800107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected CoreService coreService;
109
yoonseon214963b2016-11-21 15:41:07 -0800110 private final InternalVirtualIntentListener intentListener =
111 new InternalVirtualIntentListener();
Brian Stanke11f6d532016-07-05 16:17:59 -0400112
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500113 private VirtualNetworkStoreDelegate delegate = this::post;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700114
yoonseonc6a69272017-01-12 18:22:20 -0800115 private ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
yoonseon322c9c32016-12-07 16:47:02 -0800116 private ApplicationId appId;
yoonseonc6a69272017-01-12 18:22:20 -0800117
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700118 // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700119
Brian Stanke11f6d532016-07-05 16:17:59 -0400120 /**
121 * Only used for Junit test methods outside of this package.
122 *
123 * @param store virtual network store
124 */
125 public void setStore(VirtualNetworkStore store) {
126 this.store = store;
127 }
128
129 /**
130 * Only used for Junit test methods outside of this package.
131 *
132 * @param intentService intent service
133 */
134
135 public void setIntentService(IntentService intentService) {
136 this.intentService = intentService;
137 }
138
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700139 @Activate
Brian Stanke11f6d532016-07-05 16:17:59 -0400140 public void activate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700141 store.setDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500142 eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
Brian Stanke11f6d532016-07-05 16:17:59 -0400143 intentService.addListener(intentListener);
yoonseon322c9c32016-12-07 16:47:02 -0800144 appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700145 log.info("Started");
146 }
147
148 @Deactivate
Brian Stanke11f6d532016-07-05 16:17:59 -0400149 public void deactivate() {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700150 store.unsetDelegate(delegate);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500151 eventDispatcher.removeSink(VirtualNetworkEvent.class);
Brian Stanke11f6d532016-07-05 16:17:59 -0400152 intentService.removeListener(intentListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700153 log.info("Stopped");
154 }
155
156 @Override
157 public void registerTenantId(TenantId tenantId) {
158 checkNotNull(tenantId, TENANT_NULL);
159 store.addTenantId(tenantId);
160 }
161
162 @Override
163 public void unregisterTenantId(TenantId tenantId) {
164 checkNotNull(tenantId, TENANT_NULL);
165 store.removeTenantId(tenantId);
166 }
167
168 @Override
169 public Set<TenantId> getTenantIds() {
170 return store.getTenantIds();
171 }
172
173 @Override
174 public VirtualNetwork createVirtualNetwork(TenantId tenantId) {
175 checkNotNull(tenantId, TENANT_NULL);
176 return store.addNetwork(tenantId);
177 }
178
179 @Override
180 public void removeVirtualNetwork(NetworkId networkId) {
181 checkNotNull(networkId, NETWORK_NULL);
182 store.removeNetwork(networkId);
183 }
184
185 @Override
186 public VirtualDevice createVirtualDevice(NetworkId networkId, DeviceId deviceId) {
187 checkNotNull(networkId, NETWORK_NULL);
188 checkNotNull(deviceId, DEVICE_NULL);
189 return store.addDevice(networkId, deviceId);
190 }
191
192 @Override
193 public void removeVirtualDevice(NetworkId networkId, DeviceId deviceId) {
194 checkNotNull(networkId, NETWORK_NULL);
195 checkNotNull(deviceId, DEVICE_NULL);
196 store.removeDevice(networkId, deviceId);
197 }
198
199 @Override
yoonseon214963b2016-11-21 15:41:07 -0800200 public VirtualHost createVirtualHost(NetworkId networkId, HostId hostId,
201 MacAddress mac, VlanId vlan,
202 HostLocation location, Set<IpAddress> ips) {
Brian Stanke7a81b532016-06-14 15:43:51 -0400203 checkNotNull(networkId, NETWORK_NULL);
204 checkNotNull(hostId, DEVICE_NULL);
205 return store.addHost(networkId, hostId, mac, vlan, location, ips);
206 }
207
208 @Override
209 public void removeVirtualHost(NetworkId networkId, HostId hostId) {
210 checkNotNull(networkId, NETWORK_NULL);
211 checkNotNull(hostId, DEVICE_NULL);
212 store.removeHost(networkId, hostId);
213 }
214
215 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700216 public VirtualLink createVirtualLink(NetworkId networkId,
Brian Stanke9a108972016-04-11 15:25:17 -0400217 ConnectPoint src, ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700218 checkNotNull(networkId, NETWORK_NULL);
219 checkNotNull(src, LINK_POINT_NULL);
220 checkNotNull(dst, LINK_POINT_NULL);
Brian Stankefb61df42016-07-25 11:47:51 -0400221 ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
222 checkNotNull(physicalSrc, LINK_POINT_NULL);
223 ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
224 checkNotNull(physicalDst, LINK_POINT_NULL);
225
226 VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
227 Link.State state = Link.State.INACTIVE;
228 if (provider != null) {
229 boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
230 state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
231 }
232 return store.addLink(networkId, src, dst, state, null);
233 }
234
235 /**
236 * Maps the virtual connect point to a physical connect point.
237 *
238 * @param networkId network identifier
239 * @param virtualCp virtual connect point
240 * @return physical connect point
241 */
242 private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
243 ConnectPoint virtualCp) {
244 Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
245 for (VirtualPort port : ports) {
246 if (port.number().equals(virtualCp.port())) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700247 return new ConnectPoint(port.realizedBy().deviceId(),
248 port.realizedBy().port());
Brian Stankefb61df42016-07-25 11:47:51 -0400249 }
250 }
251 return null;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700252 }
253
Brian Stanke612cebf2016-05-02 10:21:33 -0400254 /**
255 * Maps the physical connect point to a virtual connect point.
256 *
Brian Stanke11f6d532016-07-05 16:17:59 -0400257 * @param networkId network identifier
Brian Stanke612cebf2016-05-02 10:21:33 -0400258 * @param physicalCp physical connect point
259 * @return virtual connect point
260 */
261 private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
Brian Stanke11f6d532016-07-05 16:17:59 -0400262 ConnectPoint physicalCp) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400263 Set<VirtualPort> ports = store.getPorts(networkId, null);
264 for (VirtualPort port : ports) {
Yoonseon Han6c603892016-09-01 11:52:21 -0700265 if (port.realizedBy().deviceId().equals(physicalCp.elementId()) &&
266 port.realizedBy().port().equals(physicalCp.port())) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400267 return new ConnectPoint(port.element().id(), port.number());
268 }
269 }
270 return null;
271 }
272
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700273 @Override
yoonseon214963b2016-11-21 15:41:07 -0800274 public void removeVirtualLink(NetworkId networkId, ConnectPoint src,
275 ConnectPoint dst) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700276 checkNotNull(networkId, NETWORK_NULL);
277 checkNotNull(src, LINK_POINT_NULL);
278 checkNotNull(dst, LINK_POINT_NULL);
Brian Stanke11f6d532016-07-05 16:17:59 -0400279 store.removeLink(networkId, src, dst);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700280 }
281
282 @Override
283 public VirtualPort createVirtualPort(NetworkId networkId, DeviceId deviceId,
Yoonseon Han6c603892016-09-01 11:52:21 -0700284 PortNumber portNumber, ConnectPoint realizedBy) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700285 checkNotNull(networkId, NETWORK_NULL);
286 checkNotNull(deviceId, DEVICE_NULL);
287 checkNotNull(portNumber, "Port description cannot be null");
288 return store.addPort(networkId, deviceId, portNumber, realizedBy);
289 }
290
291 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700292 public void bindVirtualPort(NetworkId networkId, DeviceId deviceId,
293 PortNumber portNumber, ConnectPoint realizedBy) {
294 checkNotNull(networkId, NETWORK_NULL);
295 checkNotNull(deviceId, DEVICE_NULL);
296 checkNotNull(portNumber, "Port description cannot be null");
297 checkNotNull(realizedBy, "Physical port description cannot be null");
298
299 store.bindPort(networkId, deviceId, portNumber, realizedBy);
300 }
301
302 @Override
yoonseon214963b2016-11-21 15:41:07 -0800303 public void removeVirtualPort(NetworkId networkId, DeviceId deviceId,
304 PortNumber portNumber) {
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700305 checkNotNull(networkId, NETWORK_NULL);
306 checkNotNull(deviceId, DEVICE_NULL);
307 checkNotNull(portNumber, "Port number cannot be null");
308 store.removePort(networkId, deviceId, portNumber);
309 }
310
311 @Override
yoonseonc6a69272017-01-12 18:22:20 -0800312 public ServiceDirectory getServiceDirectory() {
313 return serviceDirectory;
314 }
315
316 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700317 public Set<VirtualNetwork> getVirtualNetworks(TenantId tenantId) {
318 checkNotNull(tenantId, TENANT_NULL);
319 return store.getNetworks(tenantId);
320 }
321
Brian Stanke11f6d532016-07-05 16:17:59 -0400322 /**
323 * Returns the virtual network matching the network identifier.
324 *
325 * @param networkId network identifier
326 * @return virtual network
327 */
Brian Stanke86914282016-05-25 15:36:50 -0400328 private VirtualNetwork getVirtualNetwork(NetworkId networkId) {
329 checkNotNull(networkId, NETWORK_NULL);
330 return store.getNetwork(networkId);
331 }
332
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700333 @Override
334 public Set<VirtualDevice> getVirtualDevices(NetworkId networkId) {
335 checkNotNull(networkId, NETWORK_NULL);
336 return store.getDevices(networkId);
337 }
338
339 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400340 public Set<VirtualHost> getVirtualHosts(NetworkId networkId) {
341 checkNotNull(networkId, NETWORK_NULL);
342 return store.getHosts(networkId);
343 }
344
345 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700346 public Set<VirtualLink> getVirtualLinks(NetworkId networkId) {
347 checkNotNull(networkId, NETWORK_NULL);
348 return store.getLinks(networkId);
349 }
350
351 @Override
352 public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
353 checkNotNull(networkId, NETWORK_NULL);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700354 return store.getPorts(networkId, deviceId);
355 }
356
Brian Stanke86914282016-05-25 15:36:50 -0400357 private final Map<ServiceKey, VnetService> networkServices = Maps.newConcurrentMap();
358
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700359 @Override
360 public <T> T get(NetworkId networkId, Class<T> serviceClass) {
361 checkNotNull(networkId, NETWORK_NULL);
Brian Stanke86914282016-05-25 15:36:50 -0400362 ServiceKey serviceKey = networkServiceKey(networkId, serviceClass);
363 VnetService service = lookup(serviceKey);
364 if (service == null) {
365 service = create(serviceKey);
366 }
367 return (T) service;
368 }
369
yoonseon322c9c32016-12-07 16:47:02 -0800370 @Override
371 public ApplicationId getVirtualNetworkApplicationId(NetworkId networkId) {
372 return appId;
373 }
374
Brian Stanke11f6d532016-07-05 16:17:59 -0400375 /**
376 * Returns the Vnet service matching the service key.
377 *
378 * @param serviceKey service key
379 * @return vnet service
380 */
Brian Stanke86914282016-05-25 15:36:50 -0400381 private VnetService lookup(ServiceKey serviceKey) {
382 return networkServices.get(serviceKey);
383 }
384
Brian Stanke11f6d532016-07-05 16:17:59 -0400385 /**
386 * Creates a new service key using the specified network identifier and service class.
387 *
388 * @param networkId network identifier
389 * @param serviceClass service class
390 * @param <T> type of service
391 * @return service key
392 */
Brian Stanke86914282016-05-25 15:36:50 -0400393 private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) {
394 return new ServiceKey(networkId, serviceClass);
395 }
396
397
Brian Stanke11f6d532016-07-05 16:17:59 -0400398 /**
399 * Create a new vnet service instance.
400 *
401 * @param serviceKey service key
402 * @return vnet service
403 */
Brian Stanke86914282016-05-25 15:36:50 -0400404 private VnetService create(ServiceKey serviceKey) {
405 VirtualNetwork network = getVirtualNetwork(serviceKey.networkId());
Brian Stanke11f6d532016-07-05 16:17:59 -0400406 checkNotNull(network, NETWORK_NULL);
yoonseonc6a69272017-01-12 18:22:20 -0800407
Brian Stanke86914282016-05-25 15:36:50 -0400408 VnetService service;
409 if (serviceKey.serviceClass.equals(DeviceService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800410 service = new VirtualNetworkDeviceManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400411 } else if (serviceKey.serviceClass.equals(LinkService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800412 service = new VirtualNetworkLinkManager(this, network.id());
Brian Stanke8e9f8d12016-06-08 14:48:33 -0400413 } else if (serviceKey.serviceClass.equals(TopologyService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800414 service = new VirtualNetworkTopologyManager(this, network.id());
Brian Stanke11f6d532016-07-05 16:17:59 -0400415 } else if (serviceKey.serviceClass.equals(IntentService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800416 service = new VirtualNetworkIntentManager(this, network.id());
Claudine Chiu30a8a2a2016-07-14 17:09:04 -0400417 } else if (serviceKey.serviceClass.equals(HostService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800418 service = new VirtualNetworkHostManager(this, network.id());
Claudine Chiu45920dd2016-07-28 19:19:46 +0000419 } else if (serviceKey.serviceClass.equals(PathService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800420 service = new VirtualNetworkPathManager(this, network.id());
Claudine Chiu70222ad2016-11-17 22:29:20 -0500421 } else if (serviceKey.serviceClass.equals(FlowRuleService.class)) {
yoonseonc6a69272017-01-12 18:22:20 -0800422 service = new VirtualNetworkFlowRuleManager(this, network.id());
yoonseon322c9c32016-12-07 16:47:02 -0800423 } else if (serviceKey.serviceClass.equals(PacketService.class)) {
424 service = new VirtualNetworkPacketManager(this, network.id());
yoonseondc3210d2017-01-25 16:03:10 -0800425 } else if (serviceKey.serviceClass.equals(GroupService.class)) {
426 service = new VirtualNetworkGroupManager(this, network.id());
Brian Stanke86914282016-05-25 15:36:50 -0400427 } else {
428 return null;
429 }
430 networkServices.put(serviceKey, service);
431 return service;
432 }
433
Brian Stanke11f6d532016-07-05 16:17:59 -0400434 /**
435 * Service key class.
436 */
Brian Stanke86914282016-05-25 15:36:50 -0400437 private class ServiceKey {
438 final NetworkId networkId;
439 final Class serviceClass;
440
Brian Stanke11f6d532016-07-05 16:17:59 -0400441 /**
442 * Constructor for service key.
443 *
444 * @param networkId network identifier
445 * @param serviceClass service class
446 */
Brian Stanke86914282016-05-25 15:36:50 -0400447 public ServiceKey(NetworkId networkId, Class serviceClass) {
yoonseon214963b2016-11-21 15:41:07 -0800448
Brian Stanke86914282016-05-25 15:36:50 -0400449 checkNotNull(networkId, NETWORK_NULL);
450 this.networkId = networkId;
451 this.serviceClass = serviceClass;
452 }
453
Brian Stanke11f6d532016-07-05 16:17:59 -0400454 /**
455 * Returns the network identifier.
456 *
457 * @return network identifier
458 */
Brian Stanke86914282016-05-25 15:36:50 -0400459 public NetworkId networkId() {
460 return networkId;
461 }
462
Brian Stanke11f6d532016-07-05 16:17:59 -0400463 /**
464 * Returns the service class.
465 *
466 * @return service class
467 */
Brian Stanke86914282016-05-25 15:36:50 -0400468 public Class serviceClass() {
469 return serviceClass;
470 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700471 }
472
Brian Stanke11f6d532016-07-05 16:17:59 -0400473 /**
474 * Internal intent event listener.
475 */
476 private class InternalVirtualIntentListener implements IntentListener {
yoonseon214963b2016-11-21 15:41:07 -0800477
Brian Stanke11f6d532016-07-05 16:17:59 -0400478 @Override
479 public void event(IntentEvent event) {
480
481 // Ignore intent events that are not relevant.
482 if (!isRelevant(event)) {
483 return;
484 }
485
486 VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject();
487
488 switch (event.type()) {
489 case INSTALL_REQ:
490 store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ);
491 break;
492 case INSTALLED:
493 store.addOrUpdateIntent(intent, IntentState.INSTALLED);
494 break;
495 case WITHDRAW_REQ:
496 store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ);
497 break;
498 case WITHDRAWN:
499 store.addOrUpdateIntent(intent, IntentState.WITHDRAWN);
500 break;
501 case FAILED:
502 store.addOrUpdateIntent(intent, IntentState.FAILED);
503 break;
504 case CORRUPT:
505 store.addOrUpdateIntent(intent, IntentState.CORRUPT);
506 break;
507 case PURGED:
508 store.removeIntent(intent.key());
509 default:
510 break;
511 }
512 }
513
514 @Override
515 public boolean isRelevant(IntentEvent event) {
516 if (event.subject() instanceof VirtualNetworkIntent) {
517 return true;
518 }
519 return false;
520 }
521 }
522
523
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700524 @Override
yoonseon214963b2016-11-21 15:41:07 -0800525 protected VirtualNetworkProviderService
526 createProviderService(VirtualNetworkProvider provider) {
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700527 return new InternalVirtualNetworkProviderService(provider);
528 }
529
yoonseon6b972c32016-12-06 16:45:03 -0800530
Brian Stankefb61df42016-07-25 11:47:51 -0400531 /**
532 * Service issued to registered virtual network providers so that they
533 * can interact with the core.
534 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700535 private class InternalVirtualNetworkProviderService
536 extends AbstractProviderService<VirtualNetworkProvider>
537 implements VirtualNetworkProviderService {
Brian Stankefb61df42016-07-25 11:47:51 -0400538 /**
539 * Constructor.
540 * @param provider virtual network provider
541 */
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700542 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
543 super(provider);
544 }
Brian Stanke4d579882016-04-22 13:28:46 -0400545
546 @Override
Brian Stankefb61df42016-07-25 11:47:51 -0400547 public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
Brian Stankefb61df42016-07-25 11:47:51 -0400548 Set<TenantId> tenantIds = getTenantIds();
549 tenantIds.forEach(tenantId -> {
550 Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
551
552 virtualNetworks.forEach(virtualNetwork -> {
553 Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
554
555 virtualLinks.forEach(virtualLink -> {
yoonseon214963b2016-11-21 15:41:07 -0800556 if (isVirtualLinkInCluster(virtualNetwork.id(),
557 virtualLink, clusters)) {
558 store.updateLink(virtualLink, virtualLink.tunnelId(),
559 Link.State.ACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400560 } else {
yoonseon214963b2016-11-21 15:41:07 -0800561 store.updateLink(virtualLink, virtualLink.tunnelId(),
562 Link.State.INACTIVE);
Brian Stankefb61df42016-07-25 11:47:51 -0400563 }
564 });
565 });
566 });
567 }
568
569 /**
yoonseon214963b2016-11-21 15:41:07 -0800570 * Determines if the virtual link (both source and destination connect point)
571 * is in a cluster.
Brian Stankefb61df42016-07-25 11:47:51 -0400572 *
573 * @param networkId virtual network identifier
574 * @param virtualLink virtual link
575 * @param clusters topology clusters
576 * @return true if the virtual link is in a cluster.
577 */
578 private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
579 Set<Set<ConnectPoint>> clusters) {
yoonseon214963b2016-11-21 15:41:07 -0800580 ConnectPoint srcPhysicalCp =
581 mapVirtualToPhysicalPort(networkId, virtualLink.src());
582 ConnectPoint dstPhysicalCp =
583 mapVirtualToPhysicalPort(networkId, virtualLink.dst());
Brian Stankefb61df42016-07-25 11:47:51 -0400584
585 final boolean[] foundSrc = {false};
586 final boolean[] foundDst = {false};
587 clusters.forEach(connectPoints -> {
588 connectPoints.forEach(connectPoint -> {
589 if (connectPoint.equals(srcPhysicalCp)) {
590 foundSrc[0] = true;
591 } else if (connectPoint.equals(dstPhysicalCp)) {
592 foundDst[0] = true;
593 }
594 });
595 if (foundSrc[0] && foundDst[0]) {
596 return;
597 }
598 });
599 return foundSrc[0] && foundDst[0];
600 }
601
602 @Override
yoonseon214963b2016-11-21 15:41:07 -0800603 public void tunnelUp(NetworkId networkId, ConnectPoint src,
604 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400605 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
606 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
607 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
608 log.error("Src or dst virtual connection point was not found.");
609 }
610
611 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
612 if (virtualLink != null) {
613 store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
614 }
Brian Stanke4d579882016-04-22 13:28:46 -0400615 }
616
617 @Override
yoonseon214963b2016-11-21 15:41:07 -0800618 public void tunnelDown(NetworkId networkId, ConnectPoint src,
619 ConnectPoint dst, TunnelId tunnelId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400620 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
621 ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
622 if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
623 log.error("Src or dst virtual connection point was not found.");
624 }
Brian Stanke4d579882016-04-22 13:28:46 -0400625
Brian Stanke612cebf2016-05-02 10:21:33 -0400626 VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
627 if (virtualLink != null) {
628 store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
629 }
Brian Stanke4d579882016-04-22 13:28:46 -0400630 }
Thomas Vachuska3d62fd72015-09-25 14:58:13 -0700631 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700632}