blob: 24c8205a453e64a8682caf6fb394f2f103809796 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska33979fd2015-07-31 11:41:14 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.incubator.store.virtual.impl;
17
Brian Stanke0e5c94e2016-03-08 11:20:04 -050018import com.google.common.collect.ImmutableSet;
19import com.google.common.collect.Sets;
Brian Stanke7a81b532016-06-14 15:43:51 -040020import org.onlab.packet.IpAddress;
21import org.onlab.packet.MacAddress;
22import org.onlab.packet.VlanId;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050023import org.onlab.util.KryoNamespace;
24import org.onosproject.core.CoreService;
25import org.onosproject.core.IdGenerator;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070026import org.onosproject.incubator.net.tunnel.TunnelId;
27import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040028import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050029import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070030import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050031import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
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.VirtualNetworkEvent;
Brian Stanke11f6d532016-07-05 16:17:59 -040039import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050040import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070041import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
42import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
43import org.onosproject.incubator.net.virtual.VirtualPort;
44import org.onosproject.net.ConnectPoint;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050045import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070046import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040047import org.onosproject.net.HostId;
48import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040049import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070050import org.onosproject.net.PortNumber;
Brian Stanke11f6d532016-07-05 16:17:59 -040051import org.onosproject.net.intent.Intent;
Brian Stanke11f6d532016-07-05 16:17:59 -040052import org.onosproject.net.intent.Key;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070053import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050054import org.onosproject.store.serializers.KryoNamespaces;
55import org.onosproject.store.service.ConsistentMap;
56import org.onosproject.store.service.DistributedSet;
57import org.onosproject.store.service.MapEvent;
58import org.onosproject.store.service.MapEventListener;
59import org.onosproject.store.service.Serializer;
60import org.onosproject.store.service.SetEvent;
61import org.onosproject.store.service.SetEventListener;
62import org.onosproject.store.service.StorageService;
Brian Stanke11f6d532016-07-05 16:17:59 -040063import org.onosproject.store.service.WallClockTimestamp;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070064import org.osgi.service.component.annotations.Activate;
65import org.osgi.service.component.annotations.Component;
66import org.osgi.service.component.annotations.Deactivate;
67import org.osgi.service.component.annotations.Reference;
68import org.osgi.service.component.annotations.ReferenceCardinality;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070069import org.slf4j.Logger;
70
Brian Stanke0e5c94e2016-03-08 11:20:04 -050071import java.util.HashSet;
72import java.util.Map;
Yoonseon Hanaa256052017-05-08 16:25:38 -070073import java.util.Objects;
Harold Huangb7d6b8e2017-04-03 17:13:33 +080074import java.util.Optional;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070075import java.util.Set;
Claudine Chiu7f872a72016-12-16 13:51:39 -050076import java.util.concurrent.atomic.AtomicBoolean;
Claudine Chiu945828d2016-11-21 12:47:07 -050077import java.util.function.BiFunction;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070078
Brian Stanke0e5c94e2016-03-08 11:20:04 -050079import static com.google.common.base.Preconditions.checkNotNull;
80import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070081import static org.slf4j.LoggerFactory.getLogger;
82
83/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050084 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070085 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070086@Component(immediate = true, service = VirtualNetworkStore.class)
Thomas Vachuska33979fd2015-07-31 11:41:14 -070087public class DistributedVirtualNetworkStore
88 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
89 implements VirtualNetworkStore {
90
91 private final Logger log = getLogger(getClass());
92
Ray Milkeyd84f89b2018-08-17 14:54:17 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Brian Stanke0e5c94e2016-03-08 11:20:04 -050094 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070095
Ray Milkeyd84f89b2018-08-17 14:54:17 -070096 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Brian Stanke0e5c94e2016-03-08 11:20:04 -050097 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070098
Brian Stanke0e5c94e2016-03-08 11:20:04 -050099 private IdGenerator idGenerator;
100
101 // Track tenants by ID
102 private DistributedSet<TenantId> tenantIdSet;
103
104 // Listener for tenant events
105 private final SetEventListener<TenantId> setListener = new InternalSetListener();
106
107 // Track virtual networks by network Id
108 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
109 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
110
111 // Listener for virtual network events
Claudine Chiu945828d2016-11-21 12:47:07 -0500112 private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
113 new InternalMapListener<>((mapEventType, virtualNetwork) -> {
114 VirtualNetworkEvent.Type eventType =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900115 mapEventType.equals(MapEvent.Type.INSERT)
116 ? VirtualNetworkEvent.Type.NETWORK_ADDED :
117 mapEventType.equals(MapEvent.Type.UPDATE)
118 ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
119 mapEventType.equals(MapEvent.Type.REMOVE)
120 ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
Claudine Chiu945828d2016-11-21 12:47:07 -0500121 return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
122 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500123
sangyun-han3c3e99e2017-02-08 15:30:53 +0900124 // Listener for virtual device events
Yoonseon Hanaa256052017-05-08 16:25:38 -0700125 private final MapEventListener<VirtualDeviceId, VirtualDevice> virtualDeviceMapListener =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900126 new InternalMapListener<>((mapEventType, virtualDevice) -> {
127 VirtualNetworkEvent.Type eventType =
128 mapEventType.equals(MapEvent.Type.INSERT)
129 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
130 mapEventType.equals(MapEvent.Type.UPDATE)
131 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
132 mapEventType.equals(MapEvent.Type.REMOVE)
133 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
134 return eventType == null ? null :
135 new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
136 });
137
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500138 // Track virtual network IDs by tenant Id
139 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
140 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
141
142 // Track virtual devices by device Id
Yoonseon Hanaa256052017-05-08 16:25:38 -0700143 private ConsistentMap<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
144 private Map<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500145
146 // Track device IDs by network Id
147 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
148 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
149
Brian Stanke7a81b532016-06-14 15:43:51 -0400150 // Track virtual hosts by host Id
151 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
152 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
153
154 // Track host IDs by network Id
155 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
156 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
157
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500158 // Track virtual links by network Id
159 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
160 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
161
162 // Track virtual ports by network Id
163 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
164 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
165
Brian Stanke11f6d532016-07-05 16:17:59 -0400166 // Track intent ID to TunnelIds
167 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
168 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
169
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500170 private static final Serializer SERIALIZER = Serializer
171 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
172 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700173 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500174 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500175 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500176 .register(VirtualDevice.class)
Yoonseon Hanaa256052017-05-08 16:25:38 -0700177 .register(VirtualDeviceId.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500178 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400179 .register(VirtualHost.class)
180 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500181 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500182 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500183 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500184 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500185 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400186 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400187 .register(VirtualNetworkIntent.class)
188 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700189 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400190 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500191
192 /**
193 * Distributed network store service activate method.
194 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700195 @Activate
196 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500197 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
198
199 tenantIdSet = storageService.<TenantId>setBuilder()
200 .withSerializer(SERIALIZER)
201 .withName("onos-tenantId")
202 .withRelaxedReadConsistency()
203 .build()
204 .asDistributedSet();
205 tenantIdSet.addListener(setListener);
206
207 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
208 .withSerializer(SERIALIZER)
209 .withName("onos-networkId-virtualnetwork")
210 .withRelaxedReadConsistency()
211 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500212 networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500213 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
214
215 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
216 .withSerializer(SERIALIZER)
217 .withName("onos-tenantId-networkIds")
218 .withRelaxedReadConsistency()
219 .build();
220 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
221
Yoonseon Hanaa256052017-05-08 16:25:38 -0700222 deviceIdVirtualDeviceConsistentMap = storageService.<VirtualDeviceId, VirtualDevice>consistentMapBuilder()
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500223 .withSerializer(SERIALIZER)
224 .withName("onos-deviceId-virtualdevice")
225 .withRelaxedReadConsistency()
226 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500227 deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500228 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
229
230 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
231 .withSerializer(SERIALIZER)
232 .withName("onos-networkId-deviceIds")
233 .withRelaxedReadConsistency()
234 .build();
235 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
236
Brian Stanke7a81b532016-06-14 15:43:51 -0400237 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
238 .withSerializer(SERIALIZER)
239 .withName("onos-hostId-virtualhost")
240 .withRelaxedReadConsistency()
241 .build();
242 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
243
244 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
245 .withSerializer(SERIALIZER)
246 .withName("onos-networkId-hostIds")
247 .withRelaxedReadConsistency()
248 .build();
249 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
250
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500251 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
252 .withSerializer(SERIALIZER)
253 .withName("onos-networkId-virtuallinks")
254 .withRelaxedReadConsistency()
255 .build();
256 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
257
258 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
259 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400260 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500261 .withRelaxedReadConsistency()
262 .build();
263 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
264
Brian Stanke11f6d532016-07-05 16:17:59 -0400265 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
266 .withSerializer(SERIALIZER)
267 .withName("onos-intentKey-tunnelIds")
268 .withRelaxedReadConsistency()
269 .build();
270 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
271
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700272 log.info("Started");
273 }
274
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500275 /**
276 * Distributed network store service deactivate method.
277 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700278 @Deactivate
279 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500280 tenantIdSet.removeListener(setListener);
Claudine Chiu945828d2016-11-21 12:47:07 -0500281 networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
282 deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700283 log.info("Stopped");
284 }
285
286 @Override
287 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500288 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700289 }
290
291 @Override
292 public void removeTenantId(TenantId tenantId) {
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800293 //Remove all the virtual networks of this tenant
294 Set<VirtualNetwork> networkIdSet = getNetworks(tenantId);
295 if (networkIdSet != null) {
296 networkIdSet.forEach(virtualNetwork -> removeNetwork(virtualNetwork.id()));
297 }
298
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500299 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700300 }
301
302 @Override
303 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500304 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700305 }
306
307 @Override
308 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500309
310 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
311 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
312 //TODO update both maps in one transaction.
313 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500314
315 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
316 if (networkIdSet == null) {
317 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500318 }
Brian Stanke5df14472016-03-11 19:34:38 -0500319 networkIdSet.add(virtualNetwork.id());
320 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
321
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500322 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700323 }
324
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500325 /**
326 * Returns a new network identifier from a virtual network block of identifiers.
327 *
328 * @return NetworkId network identifier
329 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700330 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900331 NetworkId networkId;
332 do {
333 networkId = NetworkId.networkId(idGenerator.getNewId());
334 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700335
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900336 return networkId;
337 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700338
339 @Override
340 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500341 // Make sure that the virtual network exists before attempting to remove it.
Claudine Chiu70e2db82017-05-04 09:53:11 -0400342 checkState(networkExists(networkId), "The network does not exist.");
Brian Stanke5df14472016-03-11 19:34:38 -0500343
Claudine Chiu70e2db82017-05-04 09:53:11 -0400344 //Remove all the devices of this network
345 Set<VirtualDevice> deviceSet = getDevices(networkId);
346 if (deviceSet != null) {
347 deviceSet.forEach(virtualDevice -> removeDevice(networkId, virtualDevice.id()));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500348 }
Claudine Chiu70e2db82017-05-04 09:53:11 -0400349 //TODO update both maps in one transaction.
350
351 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
352 if (virtualNetwork == null) {
353 return;
354 }
355 TenantId tenantId = virtualNetwork.tenantId();
356
357 Set<NetworkId> networkIdSet = new HashSet<>();
358 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
359 if (networkId1.id().equals(networkId.id())) {
360 networkIdSet.add(networkId1);
361 }
362 });
363
364 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
365 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
366 return new HashSet<>();
367 } else {
368 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
369 }
370 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500371 }
372
373 /**
374 * Returns if the network identifier exists.
375 *
376 * @param networkId network identifier
377 * @return true if the network identifier exists, false otherwise.
378 */
379 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400380 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500381 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700382 }
383
384 @Override
385 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500386 checkState(networkExists(networkId), "The network has not been added.");
Yoonseon Hanaa256052017-05-08 16:25:38 -0700387
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500388 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
389 if (deviceIdSet == null) {
390 deviceIdSet = new HashSet<>();
391 }
Yoonseon Hanaa256052017-05-08 16:25:38 -0700392
393 checkState(!deviceIdSet.contains(deviceId), "The device already exists.");
394
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500395 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
396 //TODO update both maps in one transaction.
Yoonseon Hanaa256052017-05-08 16:25:38 -0700397 deviceIdVirtualDeviceMap.put(new VirtualDeviceId(networkId, deviceId), virtualDevice);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500398 deviceIdSet.add(deviceId);
399 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
400 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700401 }
402
403 @Override
404 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500405 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800406 //Remove all the virtual ports of the this device
407 Set<VirtualPort> virtualPorts = getPorts(networkId, deviceId);
408 if (virtualPorts != null) {
409 virtualPorts.forEach(virtualPort -> removePort(networkId, deviceId, virtualPort.number()));
410 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500411 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500412
413 Set<DeviceId> deviceIdSet = new HashSet<>();
414 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
415 if (deviceId1.equals(deviceId)) {
416 deviceIdSet.add(deviceId1);
417 }
418 });
419
Yoonseon Hanaa256052017-05-08 16:25:38 -0700420 if (!deviceIdSet.isEmpty()) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500421 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
422 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700423 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500424 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700425 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500426 }
427 });
428
Yoonseon Hanaa256052017-05-08 16:25:38 -0700429 deviceIdVirtualDeviceMap.remove(new VirtualDeviceId(networkId, deviceId));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500430 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400431 }
432
433 @Override
434 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
435 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
436 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800437 checkState(virtualPortExists(networkId, location.deviceId(), location.port()),
438 "The virtual port has not been created.");
Brian Stanke7a81b532016-06-14 15:43:51 -0400439 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
440 if (hostIdSet == null) {
441 hostIdSet = new HashSet<>();
442 }
443 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
444 //TODO update both maps in one transaction.
445 hostIdVirtualHostMap.put(hostId, virtualhost);
446 hostIdSet.add(hostId);
447 networkIdHostIdSetMap.put(networkId, hostIdSet);
448 return virtualhost;
449 }
450
451 @Override
452 public void removeHost(NetworkId networkId, HostId hostId) {
453 checkState(networkExists(networkId), "The network has not been added.");
454 //TODO update both maps in one transaction.
455
456 Set<HostId> hostIdSet = new HashSet<>();
457 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
458 if (hostId1.equals(hostId)) {
459 hostIdSet.add(hostId1);
460 }
461 });
462
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800463 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
464 if (existingHostIds == null || existingHostIds.isEmpty()) {
465 return new HashSet<>();
466 } else {
467 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
468 }
469 });
Brian Stanke7a81b532016-06-14 15:43:51 -0400470
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800471 hostIdVirtualHostMap.remove(hostId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700472 }
473
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800474 /**
475 * Returns if the given virtual port exists.
476 *
477 * @param networkId network identifier
478 * @param deviceId virtual device Id
479 * @param portNumber virtual port number
480 * @return true if the virtual port exists, false otherwise.
481 */
482 private boolean virtualPortExists(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
483 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
484 if (virtualPortSet != null) {
485 return virtualPortSet.stream().anyMatch(
486 p -> p.element().id().equals(deviceId) &&
487 p.number().equals(portNumber));
488 } else {
489 return false;
490 }
491 }
492
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700493 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400494 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
495 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500496 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800497 checkState(virtualPortExists(networkId, src.deviceId(), src.port()),
498 "The source virtual port has not been added.");
499 checkState(virtualPortExists(networkId, dst.deviceId(), dst.port()),
500 "The destination virtual port has not been added.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500501 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
502 if (virtualLinkSet == null) {
503 virtualLinkSet = new HashSet<>();
504 }
Harold Huang7362e672017-04-19 10:00:11 +0800505
Brian Stanke9a108972016-04-11 15:25:17 -0400506 // validate that the link does not already exist in this network
Harold Huang7362e672017-04-19 10:00:11 +0800507 checkState(getLink(networkId, src, dst) == null,
508 "The virtual link already exists");
509 checkState(getLink(networkId, src, null) == null,
510 "The source connection point has been used by another link");
511 checkState(getLink(networkId, null, dst) == null,
512 "The destination connection point has been used by another link");
Brian Stanke9a108972016-04-11 15:25:17 -0400513
514 VirtualLink virtualLink = DefaultVirtualLink.builder()
515 .networkId(networkId)
516 .src(src)
517 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400518 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400519 .tunnelId(realizedBy)
520 .build();
521
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500522 virtualLinkSet.add(virtualLink);
523 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
524 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700525 }
526
527 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400528 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400529 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
530 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
531 if (virtualLinkSet == null) {
532 virtualLinkSet = new HashSet<>();
Harold Huang7362e672017-04-19 10:00:11 +0800533 networkIdVirtualLinkSetMap.put(virtualLink.networkId(), virtualLinkSet);
534 log.warn("The updated virtual link {} has not been added", virtualLink);
535 return;
Brian Stanke9a108972016-04-11 15:25:17 -0400536 }
Harold Huang7362e672017-04-19 10:00:11 +0800537 if (!virtualLinkSet.remove(virtualLink)) {
538 log.warn("The updated virtual link {} does not exist", virtualLink);
539 return;
540 }
Brian Stanke9a108972016-04-11 15:25:17 -0400541
542 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
543 .networkId(virtualLink.networkId())
544 .src(virtualLink.src())
545 .dst(virtualLink.dst())
546 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400547 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400548 .build();
549
550 virtualLinkSet.add(newVirtualLink);
551 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
552 }
553
554 @Override
555 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500556 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500557
Brian Stanke9a108972016-04-11 15:25:17 -0400558 final VirtualLink virtualLink = getLink(networkId, src, dst);
559 if (virtualLink == null) {
Harold Huang7362e672017-04-19 10:00:11 +0800560 log.warn("The removed virtual link between {} and {} does not exist", src, dst);
Brian Stanke9a108972016-04-11 15:25:17 -0400561 return null;
562 }
Brian Stanke5df14472016-03-11 19:34:38 -0500563 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400564 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500565
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800566 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
567 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
568 return new HashSet<>();
569 } else {
570 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
571 }
572 });
Brian Stanke9a108972016-04-11 15:25:17 -0400573 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700574 }
575
576 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700577 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
578 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500579 checkState(networkExists(networkId), "The network has not been added.");
580 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700581
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500582 if (virtualPortSet == null) {
583 virtualPortSet = new HashSet<>();
584 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700585
Yoonseon Hanaa256052017-05-08 16:25:38 -0700586 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500587 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700588
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800589 checkState(!virtualPortExists(networkId, deviceId, portNumber),
590 "The requested Port Number has been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700591
592 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
593 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500594 virtualPortSet.add(virtualPort);
595 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500596 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400597 networkId, device, virtualPort));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500598 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700599 }
600
601 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700602 public void bindPort(NetworkId networkId, DeviceId deviceId,
603 PortNumber portNumber, ConnectPoint realizedBy) {
604
605 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
606 .get(networkId);
607
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800608 Optional<VirtualPort> virtualPortOptional = virtualPortSet.stream().filter(
Yoonseon Han6c603892016-09-01 11:52:21 -0700609 p -> p.element().id().equals(deviceId) &&
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800610 p.number().equals(portNumber)).findFirst();
611 checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700612
Yoonseon Hanaa256052017-05-08 16:25:38 -0700613 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Yoonseon Han6c603892016-09-01 11:52:21 -0700614 checkNotNull(device, "The device has not been created for deviceId: "
615 + deviceId);
616
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800617 VirtualPort vPort = virtualPortOptional.get();
Yoonseon Han6c603892016-09-01 11:52:21 -0700618 virtualPortSet.remove(vPort);
619 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
620 virtualPortSet.add(vPort);
621 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500622 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400623 networkId, device, vPort));
Yoonseon Han6c603892016-09-01 11:52:21 -0700624 }
625
626 @Override
Claudine Chiu579969d2017-10-06 14:32:18 -0400627 public void updatePortState(NetworkId networkId, DeviceId deviceId,
628 PortNumber portNumber, boolean isEnabled) {
629 checkState(networkExists(networkId), "No network with NetworkId %s exists.", networkId);
630
631 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
632 checkNotNull(device, "No device %s exists in NetworkId: %s", deviceId, networkId);
633
634 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
635 checkNotNull(virtualPortSet, "No port has been created for NetworkId: %s", networkId);
636
637 Optional<VirtualPort> virtualPortOptional = virtualPortSet.stream().filter(
638 p -> p.element().id().equals(deviceId) &&
639 p.number().equals(portNumber)).findFirst();
640 checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
641
642 VirtualPort oldPort = virtualPortOptional.get();
643 if (oldPort.isEnabled() == isEnabled) {
644 log.debug("No change in port state - port not updated");
645 return;
646 }
647 VirtualPort newPort = new DefaultVirtualPort(networkId, device, portNumber, isEnabled,
648 oldPort.realizedBy());
649 virtualPortSet.remove(oldPort);
650 virtualPortSet.add(newPort);
651 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
652 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
653 networkId, device, newPort));
654 log.debug("port state changed from {} to {}", oldPort.isEnabled(), isEnabled);
655 }
656
657 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700658 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500659 checkState(networkExists(networkId), "The network has not been added.");
Yoonseon Hanaa256052017-05-08 16:25:38 -0700660 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Claudine Chiu465a2602017-03-17 18:33:36 -0400661 checkNotNull(device, "The device has not been created for deviceId: "
662 + deviceId);
Brian Stanke5df14472016-03-11 19:34:38 -0500663
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800664 if (networkIdVirtualPortSetMap.get(networkId) == null) {
665 log.warn("No port has been created for NetworkId: {}", networkId);
666 return;
667 }
668
Brian Stanke5df14472016-03-11 19:34:38 -0500669 Set<VirtualPort> virtualPortSet = new HashSet<>();
670 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
671 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
672 virtualPortSet.add(port);
673 }
674 });
675
Claudine Chiu7f872a72016-12-16 13:51:39 -0500676 if (!virtualPortSet.isEmpty()) {
677 AtomicBoolean portRemoved = new AtomicBoolean(false);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500678 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
679 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700680 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500681 } else {
Claudine Chiu7f872a72016-12-16 13:51:39 -0500682 portRemoved.set(true);
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700683 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500684 }
685 });
Claudine Chiu7f872a72016-12-16 13:51:39 -0500686 if (portRemoved.get()) {
687 virtualPortSet.forEach(virtualPort -> notifyDelegate(
688 new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400689 networkId, device, virtualPort)
Claudine Chiu7f872a72016-12-16 13:51:39 -0500690 ));
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800691
692 //Remove all the virtual links connected to this virtual port
693 Set<VirtualLink> existingVirtualLinks = networkIdVirtualLinkSetMap.get(networkId);
694 if (existingVirtualLinks != null && !existingVirtualLinks.isEmpty()) {
695 Set<VirtualLink> virtualLinkSet = new HashSet<>();
696 ConnectPoint cp = new ConnectPoint(deviceId, portNumber);
697 existingVirtualLinks.forEach(virtualLink -> {
698 if (virtualLink.src().equals(cp) || virtualLink.dst().equals(cp)) {
699 virtualLinkSet.add(virtualLink);
700 }
701 });
702 virtualLinkSet.forEach(virtualLink ->
703 removeLink(networkId, virtualLink.src(), virtualLink.dst()));
704 }
705
706 //Remove all the hosts connected to this virtual port
707 Set<HostId> hostIdSet = new HashSet<>();
708 hostIdVirtualHostMap.forEach((hostId, virtualHost) -> {
709 if (virtualHost.location().deviceId().equals(deviceId) &&
710 virtualHost.location().port().equals(portNumber)) {
711 hostIdSet.add(hostId);
712 }
713 });
714 hostIdSet.forEach(hostId -> removeHost(networkId, hostId));
Claudine Chiu7f872a72016-12-16 13:51:39 -0500715 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500716 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700717 }
718
719 @Override
720 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500721 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
722 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
723 if (networkIdSet != null) {
Harold Huange86d35f2017-06-14 15:15:18 +0800724 networkIdSet.forEach(networkId -> {
725 if (networkIdVirtualNetworkMap.get(networkId) != null) {
726 virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId));
727 }
728 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500729 }
730 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700731 }
732
733 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400734 public VirtualNetwork getNetwork(NetworkId networkId) {
735 return networkIdVirtualNetworkMap.get(networkId);
736 }
737
738 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700739 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500740 checkState(networkExists(networkId), "The network has not been added.");
741 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
742 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
743 if (deviceIdSet != null) {
Yoonseon Hanaa256052017-05-08 16:25:38 -0700744 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(
745 deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId))));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500746 }
747 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700748 }
749
750 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400751 public Set<VirtualHost> getHosts(NetworkId networkId) {
752 checkState(networkExists(networkId), "The network has not been added.");
753 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
754 Set<VirtualHost> virtualHostSet = new HashSet<>();
755 if (hostIdSet != null) {
756 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
757 }
758 return ImmutableSet.copyOf(virtualHostSet);
759 }
760
761 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700762 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500763 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500764 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
765 if (virtualLinkSet == null) {
766 virtualLinkSet = new HashSet<>();
767 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500768 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700769 }
770
Brian Stanke612cebf2016-05-02 10:21:33 -0400771 @Override
772 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400773 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
774 if (virtualLinkSet == null) {
775 return null;
776 }
777
778 VirtualLink virtualLink = null;
779 for (VirtualLink link : virtualLinkSet) {
Harold Huang7362e672017-04-19 10:00:11 +0800780 if (src == null && link.dst().equals(dst)) {
781 virtualLink = link;
782 break;
783 } else if (dst == null && link.src().equals(src)) {
784 virtualLink = link;
785 break;
786 } else if (link.src().equals(src) && link.dst().equals(dst)) {
Brian Stanke9a108972016-04-11 15:25:17 -0400787 virtualLink = link;
788 break;
789 }
790 }
791 return virtualLink;
792 }
793
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700794 @Override
795 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500796 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500797 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
798 if (virtualPortSet == null) {
799 virtualPortSet = new HashSet<>();
800 }
801
Brian Stanke612cebf2016-05-02 10:21:33 -0400802 if (deviceId == null) {
803 return ImmutableSet.copyOf(virtualPortSet);
804 }
805
Brian Stanke5df14472016-03-11 19:34:38 -0500806 Set<VirtualPort> portSet = new HashSet<>();
807 virtualPortSet.forEach(virtualPort -> {
808 if (virtualPort.element().id().equals(deviceId)) {
809 portSet.add(virtualPort);
810 }
811 });
812 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500813 }
814
Brian Stanke11f6d532016-07-05 16:17:59 -0400815 @Override
Brian Stanke11f6d532016-07-05 16:17:59 -0400816 public void addTunnelId(Intent intent, TunnelId tunnelId) {
817 // Add the tunnelId to the intent key set map
818 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
819 if (tunnelIdSet == null) {
820 tunnelIdSet = new HashSet<>();
821 }
822 tunnelIdSet.add(tunnelId);
823 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
824 }
825
826 @Override
827 public Set<TunnelId> getTunnelIds(Intent intent) {
828 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
829 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
830 }
831
832 @Override
833 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
834 Set<TunnelId> tunnelIdSet = new HashSet<>();
835 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
836 if (tunnelId1.equals(tunnelId)) {
837 tunnelIdSet.add(tunnelId);
838 }
839 });
840
841 if (!tunnelIdSet.isEmpty()) {
842 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
843 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
844 return new HashSet<>();
845 } else {
846 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
847 }
848 });
849 }
850 }
851
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500852 /**
853 * Listener class to map listener set events to the virtual network events.
854 */
855 private class InternalSetListener implements SetEventListener<TenantId> {
856 @Override
857 public void event(SetEvent<TenantId> event) {
858 VirtualNetworkEvent.Type type = null;
859 switch (event.type()) {
860 case ADD:
861 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
862 break;
863 case REMOVE:
864 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
865 break;
866 default:
867 log.error("Unsupported event type: " + event.type());
868 }
869 notifyDelegate(new VirtualNetworkEvent(type, null));
870 }
871 }
872
873 /**
874 * Listener class to map listener map events to the virtual network events.
875 */
Claudine Chiu945828d2016-11-21 12:47:07 -0500876 private class InternalMapListener<K, V> implements MapEventListener<K, V> {
877
878 private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
879
880 InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
881 this.createEvent = createEvent;
882 }
883
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500884 @Override
Claudine Chiu945828d2016-11-21 12:47:07 -0500885 public void event(MapEvent<K, V> event) {
886 checkNotNull(event.key());
887 VirtualNetworkEvent vnetEvent = null;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500888 switch (event.type()) {
889 case INSERT:
Claudine Chiu945828d2016-11-21 12:47:07 -0500890 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500891 break;
892 case UPDATE:
893 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
Claudine Chiu945828d2016-11-21 12:47:07 -0500894 vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500895 } else {
Claudine Chiu945828d2016-11-21 12:47:07 -0500896 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500897 }
898 break;
899 case REMOVE:
Claudine Chiu945828d2016-11-21 12:47:07 -0500900 if (event.oldValue() != null) {
901 vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
902 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500903 break;
904 default:
905 log.error("Unsupported event type: " + event.type());
906 }
Claudine Chiu945828d2016-11-21 12:47:07 -0500907 if (vnetEvent != null) {
908 notifyDelegate(vnetEvent);
909 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500910 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700911 }
Yoonseon Hanaa256052017-05-08 16:25:38 -0700912
913 /**
914 * A wrapper class to isolate device id from other virtual networks.
915 */
916
917 private static class VirtualDeviceId {
918
919 NetworkId networkId;
920 DeviceId deviceId;
921
922 public VirtualDeviceId(NetworkId networkId, DeviceId deviceId) {
923 this.networkId = networkId;
924 this.deviceId = deviceId;
925 }
926
927 public NetworkId getNetworkId() {
928 return networkId;
929 }
930
931 public DeviceId getDeviceId() {
932 return deviceId;
933 }
934
935 @Override
936 public int hashCode() {
937 return Objects.hash(networkId, deviceId);
938 }
939
940 @Override
941 public boolean equals(Object obj) {
942 if (this == obj) {
943 return true;
944 }
945
946 if (obj instanceof VirtualDeviceId) {
947 VirtualDeviceId that = (VirtualDeviceId) obj;
948 return this.deviceId.equals(that.deviceId) &&
949 this.networkId.equals(that.networkId);
950 }
951 return false;
952 }
953 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700954}