blob: 1eaf1960dac691e30797e9576069308b7cdb9b13 [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;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070020import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070025import org.apache.felix.scr.annotations.Service;
Brian Stanke7a81b532016-06-14 15:43:51 -040026import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050029import org.onlab.util.KryoNamespace;
30import org.onosproject.core.CoreService;
31import org.onosproject.core.IdGenerator;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.tunnel.TunnelId;
33import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040034import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050035import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070036import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050037import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070038import org.onosproject.incubator.net.virtual.NetworkId;
39import org.onosproject.incubator.net.virtual.TenantId;
40import org.onosproject.incubator.net.virtual.VirtualDevice;
Brian Stanke7a81b532016-06-14 15:43:51 -040041import org.onosproject.incubator.net.virtual.VirtualHost;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070042import org.onosproject.incubator.net.virtual.VirtualLink;
43import org.onosproject.incubator.net.virtual.VirtualNetwork;
44import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke11f6d532016-07-05 16:17:59 -040045import org.onosproject.incubator.net.virtual.VirtualNetworkIntent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050046import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070047import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
48import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
49import org.onosproject.incubator.net.virtual.VirtualPort;
50import org.onosproject.net.ConnectPoint;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050051import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070052import org.onosproject.net.DeviceId;
Brian Stanke7a81b532016-06-14 15:43:51 -040053import org.onosproject.net.HostId;
54import org.onosproject.net.HostLocation;
Brian Stanke612cebf2016-05-02 10:21:33 -040055import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070056import org.onosproject.net.PortNumber;
Brian Stanke11f6d532016-07-05 16:17:59 -040057import org.onosproject.net.intent.Intent;
Brian Stanke11f6d532016-07-05 16:17:59 -040058import org.onosproject.net.intent.Key;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070059import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050060import org.onosproject.store.serializers.KryoNamespaces;
61import org.onosproject.store.service.ConsistentMap;
62import org.onosproject.store.service.DistributedSet;
63import org.onosproject.store.service.MapEvent;
64import org.onosproject.store.service.MapEventListener;
65import org.onosproject.store.service.Serializer;
66import org.onosproject.store.service.SetEvent;
67import org.onosproject.store.service.SetEventListener;
68import org.onosproject.store.service.StorageService;
Brian Stanke11f6d532016-07-05 16:17:59 -040069import org.onosproject.store.service.WallClockTimestamp;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070070import org.slf4j.Logger;
71
Brian Stanke0e5c94e2016-03-08 11:20:04 -050072import java.util.HashSet;
73import java.util.Map;
Yoonseon Hanaa256052017-05-08 16:25:38 -070074import java.util.Objects;
Harold Huangb7d6b8e2017-04-03 17:13:33 +080075import java.util.Optional;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070076import java.util.Set;
Claudine Chiu7f872a72016-12-16 13:51:39 -050077import java.util.concurrent.atomic.AtomicBoolean;
Claudine Chiu945828d2016-11-21 12:47:07 -050078import java.util.function.BiFunction;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070079
Brian Stanke0e5c94e2016-03-08 11:20:04 -050080import static com.google.common.base.Preconditions.checkNotNull;
81import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070082import static org.slf4j.LoggerFactory.getLogger;
83
84/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050085 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070086 */
87@Component(immediate = true)
88@Service
89public class DistributedVirtualNetworkStore
90 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
91 implements VirtualNetworkStore {
92
93 private final Logger log = getLogger(getClass());
94
Brian Stanke0e5c94e2016-03-08 11:20:04 -050095 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070097
Brian Stanke0e5c94e2016-03-08 11:20:04 -050098 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700100
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500101 private IdGenerator idGenerator;
102
103 // Track tenants by ID
104 private DistributedSet<TenantId> tenantIdSet;
105
106 // Listener for tenant events
107 private final SetEventListener<TenantId> setListener = new InternalSetListener();
108
109 // Track virtual networks by network Id
110 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
111 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
112
113 // Listener for virtual network events
Claudine Chiu945828d2016-11-21 12:47:07 -0500114 private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
115 new InternalMapListener<>((mapEventType, virtualNetwork) -> {
116 VirtualNetworkEvent.Type eventType =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900117 mapEventType.equals(MapEvent.Type.INSERT)
118 ? VirtualNetworkEvent.Type.NETWORK_ADDED :
119 mapEventType.equals(MapEvent.Type.UPDATE)
120 ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
121 mapEventType.equals(MapEvent.Type.REMOVE)
122 ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
Claudine Chiu945828d2016-11-21 12:47:07 -0500123 return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
124 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500125
sangyun-han3c3e99e2017-02-08 15:30:53 +0900126 // Listener for virtual device events
Yoonseon Hanaa256052017-05-08 16:25:38 -0700127 private final MapEventListener<VirtualDeviceId, VirtualDevice> virtualDeviceMapListener =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900128 new InternalMapListener<>((mapEventType, virtualDevice) -> {
129 VirtualNetworkEvent.Type eventType =
130 mapEventType.equals(MapEvent.Type.INSERT)
131 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
132 mapEventType.equals(MapEvent.Type.UPDATE)
133 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
134 mapEventType.equals(MapEvent.Type.REMOVE)
135 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
136 return eventType == null ? null :
137 new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
138 });
139
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500140 // Track virtual network IDs by tenant Id
141 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
142 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
143
144 // Track virtual devices by device Id
Yoonseon Hanaa256052017-05-08 16:25:38 -0700145 private ConsistentMap<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
146 private Map<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500147
148 // Track device IDs by network Id
149 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
150 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
151
Brian Stanke7a81b532016-06-14 15:43:51 -0400152 // Track virtual hosts by host Id
153 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
154 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
155
156 // Track host IDs by network Id
157 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
158 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
159
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500160 // Track virtual links by network Id
161 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
162 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
163
164 // Track virtual ports by network Id
165 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
166 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
167
Brian Stanke11f6d532016-07-05 16:17:59 -0400168 // Track intent ID to TunnelIds
169 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
170 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
171
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500172 private static final Serializer SERIALIZER = Serializer
173 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
174 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700175 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500176 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500177 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500178 .register(VirtualDevice.class)
Yoonseon Hanaa256052017-05-08 16:25:38 -0700179 .register(VirtualDeviceId.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500180 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400181 .register(VirtualHost.class)
182 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500183 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500184 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500185 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500186 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500187 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400188 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400189 .register(VirtualNetworkIntent.class)
190 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700191 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400192 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500193
194 /**
195 * Distributed network store service activate method.
196 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700197 @Activate
198 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500199 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
200
201 tenantIdSet = storageService.<TenantId>setBuilder()
202 .withSerializer(SERIALIZER)
203 .withName("onos-tenantId")
204 .withRelaxedReadConsistency()
205 .build()
206 .asDistributedSet();
207 tenantIdSet.addListener(setListener);
208
209 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
210 .withSerializer(SERIALIZER)
211 .withName("onos-networkId-virtualnetwork")
212 .withRelaxedReadConsistency()
213 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500214 networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500215 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
216
217 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
218 .withSerializer(SERIALIZER)
219 .withName("onos-tenantId-networkIds")
220 .withRelaxedReadConsistency()
221 .build();
222 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
223
Yoonseon Hanaa256052017-05-08 16:25:38 -0700224 deviceIdVirtualDeviceConsistentMap = storageService.<VirtualDeviceId, VirtualDevice>consistentMapBuilder()
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500225 .withSerializer(SERIALIZER)
226 .withName("onos-deviceId-virtualdevice")
227 .withRelaxedReadConsistency()
228 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500229 deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500230 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
231
232 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
233 .withSerializer(SERIALIZER)
234 .withName("onos-networkId-deviceIds")
235 .withRelaxedReadConsistency()
236 .build();
237 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
238
Brian Stanke7a81b532016-06-14 15:43:51 -0400239 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
240 .withSerializer(SERIALIZER)
241 .withName("onos-hostId-virtualhost")
242 .withRelaxedReadConsistency()
243 .build();
244 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
245
246 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
247 .withSerializer(SERIALIZER)
248 .withName("onos-networkId-hostIds")
249 .withRelaxedReadConsistency()
250 .build();
251 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
252
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500253 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
254 .withSerializer(SERIALIZER)
255 .withName("onos-networkId-virtuallinks")
256 .withRelaxedReadConsistency()
257 .build();
258 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
259
260 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
261 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400262 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500263 .withRelaxedReadConsistency()
264 .build();
265 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
266
Brian Stanke11f6d532016-07-05 16:17:59 -0400267 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
268 .withSerializer(SERIALIZER)
269 .withName("onos-intentKey-tunnelIds")
270 .withRelaxedReadConsistency()
271 .build();
272 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
273
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700274 log.info("Started");
275 }
276
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500277 /**
278 * Distributed network store service deactivate method.
279 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700280 @Deactivate
281 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500282 tenantIdSet.removeListener(setListener);
Claudine Chiu945828d2016-11-21 12:47:07 -0500283 networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
284 deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700285 log.info("Stopped");
286 }
287
288 @Override
289 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500290 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700291 }
292
293 @Override
294 public void removeTenantId(TenantId tenantId) {
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800295 //Remove all the virtual networks of this tenant
296 Set<VirtualNetwork> networkIdSet = getNetworks(tenantId);
297 if (networkIdSet != null) {
298 networkIdSet.forEach(virtualNetwork -> removeNetwork(virtualNetwork.id()));
299 }
300
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500301 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700302 }
303
304 @Override
305 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500306 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700307 }
308
309 @Override
310 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500311
312 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
313 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
314 //TODO update both maps in one transaction.
315 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500316
317 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
318 if (networkIdSet == null) {
319 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500320 }
Brian Stanke5df14472016-03-11 19:34:38 -0500321 networkIdSet.add(virtualNetwork.id());
322 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
323
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500324 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700325 }
326
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500327 /**
328 * Returns a new network identifier from a virtual network block of identifiers.
329 *
330 * @return NetworkId network identifier
331 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700332 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900333 NetworkId networkId;
334 do {
335 networkId = NetworkId.networkId(idGenerator.getNewId());
336 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700337
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900338 return networkId;
339 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700340
341 @Override
342 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500343 // Make sure that the virtual network exists before attempting to remove it.
Claudine Chiu70e2db82017-05-04 09:53:11 -0400344 checkState(networkExists(networkId), "The network does not exist.");
Brian Stanke5df14472016-03-11 19:34:38 -0500345
Claudine Chiu70e2db82017-05-04 09:53:11 -0400346 //Remove all the devices of this network
347 Set<VirtualDevice> deviceSet = getDevices(networkId);
348 if (deviceSet != null) {
349 deviceSet.forEach(virtualDevice -> removeDevice(networkId, virtualDevice.id()));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500350 }
Claudine Chiu70e2db82017-05-04 09:53:11 -0400351 //TODO update both maps in one transaction.
352
353 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
354 if (virtualNetwork == null) {
355 return;
356 }
357 TenantId tenantId = virtualNetwork.tenantId();
358
359 Set<NetworkId> networkIdSet = new HashSet<>();
360 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
361 if (networkId1.id().equals(networkId.id())) {
362 networkIdSet.add(networkId1);
363 }
364 });
365
366 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
367 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
368 return new HashSet<>();
369 } else {
370 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
371 }
372 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500373 }
374
375 /**
376 * Returns if the network identifier exists.
377 *
378 * @param networkId network identifier
379 * @return true if the network identifier exists, false otherwise.
380 */
381 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400382 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500383 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700384 }
385
386 @Override
387 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500388 checkState(networkExists(networkId), "The network has not been added.");
Yoonseon Hanaa256052017-05-08 16:25:38 -0700389
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500390 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
391 if (deviceIdSet == null) {
392 deviceIdSet = new HashSet<>();
393 }
Yoonseon Hanaa256052017-05-08 16:25:38 -0700394
395 checkState(!deviceIdSet.contains(deviceId), "The device already exists.");
396
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500397 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
398 //TODO update both maps in one transaction.
Yoonseon Hanaa256052017-05-08 16:25:38 -0700399 deviceIdVirtualDeviceMap.put(new VirtualDeviceId(networkId, deviceId), virtualDevice);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500400 deviceIdSet.add(deviceId);
401 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
402 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700403 }
404
405 @Override
406 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500407 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800408 //Remove all the virtual ports of the this device
409 Set<VirtualPort> virtualPorts = getPorts(networkId, deviceId);
410 if (virtualPorts != null) {
411 virtualPorts.forEach(virtualPort -> removePort(networkId, deviceId, virtualPort.number()));
412 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500413 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500414
415 Set<DeviceId> deviceIdSet = new HashSet<>();
416 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
417 if (deviceId1.equals(deviceId)) {
418 deviceIdSet.add(deviceId1);
419 }
420 });
421
Yoonseon Hanaa256052017-05-08 16:25:38 -0700422 if (!deviceIdSet.isEmpty()) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500423 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
424 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700425 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500426 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700427 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500428 }
429 });
430
Yoonseon Hanaa256052017-05-08 16:25:38 -0700431 deviceIdVirtualDeviceMap.remove(new VirtualDeviceId(networkId, deviceId));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500432 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400433 }
434
435 @Override
436 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
437 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
438 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800439 checkState(virtualPortExists(networkId, location.deviceId(), location.port()),
440 "The virtual port has not been created.");
Brian Stanke7a81b532016-06-14 15:43:51 -0400441 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
442 if (hostIdSet == null) {
443 hostIdSet = new HashSet<>();
444 }
445 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
446 //TODO update both maps in one transaction.
447 hostIdVirtualHostMap.put(hostId, virtualhost);
448 hostIdSet.add(hostId);
449 networkIdHostIdSetMap.put(networkId, hostIdSet);
450 return virtualhost;
451 }
452
453 @Override
454 public void removeHost(NetworkId networkId, HostId hostId) {
455 checkState(networkExists(networkId), "The network has not been added.");
456 //TODO update both maps in one transaction.
457
458 Set<HostId> hostIdSet = new HashSet<>();
459 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
460 if (hostId1.equals(hostId)) {
461 hostIdSet.add(hostId1);
462 }
463 });
464
465 if (hostIdSet != null) {
466 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
467 if (existingHostIds == null || existingHostIds.isEmpty()) {
468 return new HashSet<>();
469 } else {
470 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
471 }
472 });
473
474 hostIdVirtualHostMap.remove(hostId);
475 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700476 }
477
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800478 /**
479 * Returns if the given virtual port exists.
480 *
481 * @param networkId network identifier
482 * @param deviceId virtual device Id
483 * @param portNumber virtual port number
484 * @return true if the virtual port exists, false otherwise.
485 */
486 private boolean virtualPortExists(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
487 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
488 if (virtualPortSet != null) {
489 return virtualPortSet.stream().anyMatch(
490 p -> p.element().id().equals(deviceId) &&
491 p.number().equals(portNumber));
492 } else {
493 return false;
494 }
495 }
496
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700497 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400498 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
499 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500500 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800501 checkState(virtualPortExists(networkId, src.deviceId(), src.port()),
502 "The source virtual port has not been added.");
503 checkState(virtualPortExists(networkId, dst.deviceId(), dst.port()),
504 "The destination virtual port has not been added.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500505 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
506 if (virtualLinkSet == null) {
507 virtualLinkSet = new HashSet<>();
508 }
Harold Huang7362e672017-04-19 10:00:11 +0800509
Brian Stanke9a108972016-04-11 15:25:17 -0400510 // validate that the link does not already exist in this network
Harold Huang7362e672017-04-19 10:00:11 +0800511 checkState(getLink(networkId, src, dst) == null,
512 "The virtual link already exists");
513 checkState(getLink(networkId, src, null) == null,
514 "The source connection point has been used by another link");
515 checkState(getLink(networkId, null, dst) == null,
516 "The destination connection point has been used by another link");
Brian Stanke9a108972016-04-11 15:25:17 -0400517
518 VirtualLink virtualLink = DefaultVirtualLink.builder()
519 .networkId(networkId)
520 .src(src)
521 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400522 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400523 .tunnelId(realizedBy)
524 .build();
525
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500526 virtualLinkSet.add(virtualLink);
527 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
528 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700529 }
530
531 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400532 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400533 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
534 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
535 if (virtualLinkSet == null) {
536 virtualLinkSet = new HashSet<>();
Harold Huang7362e672017-04-19 10:00:11 +0800537 networkIdVirtualLinkSetMap.put(virtualLink.networkId(), virtualLinkSet);
538 log.warn("The updated virtual link {} has not been added", virtualLink);
539 return;
Brian Stanke9a108972016-04-11 15:25:17 -0400540 }
Harold Huang7362e672017-04-19 10:00:11 +0800541 if (!virtualLinkSet.remove(virtualLink)) {
542 log.warn("The updated virtual link {} does not exist", virtualLink);
543 return;
544 }
Brian Stanke9a108972016-04-11 15:25:17 -0400545
546 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
547 .networkId(virtualLink.networkId())
548 .src(virtualLink.src())
549 .dst(virtualLink.dst())
550 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400551 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400552 .build();
553
554 virtualLinkSet.add(newVirtualLink);
555 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
556 }
557
558 @Override
559 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500560 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500561
Brian Stanke9a108972016-04-11 15:25:17 -0400562 final VirtualLink virtualLink = getLink(networkId, src, dst);
563 if (virtualLink == null) {
Harold Huang7362e672017-04-19 10:00:11 +0800564 log.warn("The removed virtual link between {} and {} does not exist", src, dst);
Brian Stanke9a108972016-04-11 15:25:17 -0400565 return null;
566 }
Brian Stanke5df14472016-03-11 19:34:38 -0500567 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400568 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500569
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500570 if (virtualLinkSet != null) {
571 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
572 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700573 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500574 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700575 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500576 }
577 });
578 }
Brian Stanke9a108972016-04-11 15:25:17 -0400579 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700580 }
581
582 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700583 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
584 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500585 checkState(networkExists(networkId), "The network has not been added.");
586 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700587
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500588 if (virtualPortSet == null) {
589 virtualPortSet = new HashSet<>();
590 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700591
Yoonseon Hanaa256052017-05-08 16:25:38 -0700592 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500593 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700594
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800595 checkState(!virtualPortExists(networkId, deviceId, portNumber),
596 "The requested Port Number has been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700597
598 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
599 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500600 virtualPortSet.add(virtualPort);
601 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500602 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400603 networkId, device, virtualPort));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500604 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700605 }
606
607 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700608 public void bindPort(NetworkId networkId, DeviceId deviceId,
609 PortNumber portNumber, ConnectPoint realizedBy) {
610
611 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
612 .get(networkId);
613
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800614 Optional<VirtualPort> virtualPortOptional = virtualPortSet.stream().filter(
Yoonseon Han6c603892016-09-01 11:52:21 -0700615 p -> p.element().id().equals(deviceId) &&
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800616 p.number().equals(portNumber)).findFirst();
617 checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700618
Yoonseon Hanaa256052017-05-08 16:25:38 -0700619 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Yoonseon Han6c603892016-09-01 11:52:21 -0700620 checkNotNull(device, "The device has not been created for deviceId: "
621 + deviceId);
622
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800623 VirtualPort vPort = virtualPortOptional.get();
Yoonseon Han6c603892016-09-01 11:52:21 -0700624 virtualPortSet.remove(vPort);
625 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
626 virtualPortSet.add(vPort);
627 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500628 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400629 networkId, device, vPort));
Yoonseon Han6c603892016-09-01 11:52:21 -0700630 }
631
632 @Override
Claudine Chiu579969d2017-10-06 14:32:18 -0400633 public void updatePortState(NetworkId networkId, DeviceId deviceId,
634 PortNumber portNumber, boolean isEnabled) {
635 checkState(networkExists(networkId), "No network with NetworkId %s exists.", networkId);
636
637 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
638 checkNotNull(device, "No device %s exists in NetworkId: %s", deviceId, networkId);
639
640 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
641 checkNotNull(virtualPortSet, "No port has been created for NetworkId: %s", networkId);
642
643 Optional<VirtualPort> virtualPortOptional = virtualPortSet.stream().filter(
644 p -> p.element().id().equals(deviceId) &&
645 p.number().equals(portNumber)).findFirst();
646 checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
647
648 VirtualPort oldPort = virtualPortOptional.get();
649 if (oldPort.isEnabled() == isEnabled) {
650 log.debug("No change in port state - port not updated");
651 return;
652 }
653 VirtualPort newPort = new DefaultVirtualPort(networkId, device, portNumber, isEnabled,
654 oldPort.realizedBy());
655 virtualPortSet.remove(oldPort);
656 virtualPortSet.add(newPort);
657 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
658 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
659 networkId, device, newPort));
660 log.debug("port state changed from {} to {}", oldPort.isEnabled(), isEnabled);
661 }
662
663 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700664 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500665 checkState(networkExists(networkId), "The network has not been added.");
Yoonseon Hanaa256052017-05-08 16:25:38 -0700666 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Claudine Chiu465a2602017-03-17 18:33:36 -0400667 checkNotNull(device, "The device has not been created for deviceId: "
668 + deviceId);
Brian Stanke5df14472016-03-11 19:34:38 -0500669
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800670 if (networkIdVirtualPortSetMap.get(networkId) == null) {
671 log.warn("No port has been created for NetworkId: {}", networkId);
672 return;
673 }
674
Brian Stanke5df14472016-03-11 19:34:38 -0500675 Set<VirtualPort> virtualPortSet = new HashSet<>();
676 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
677 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
678 virtualPortSet.add(port);
679 }
680 });
681
Claudine Chiu7f872a72016-12-16 13:51:39 -0500682 if (!virtualPortSet.isEmpty()) {
683 AtomicBoolean portRemoved = new AtomicBoolean(false);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500684 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
685 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700686 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500687 } else {
Claudine Chiu7f872a72016-12-16 13:51:39 -0500688 portRemoved.set(true);
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700689 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500690 }
691 });
Claudine Chiu7f872a72016-12-16 13:51:39 -0500692 if (portRemoved.get()) {
693 virtualPortSet.forEach(virtualPort -> notifyDelegate(
694 new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400695 networkId, device, virtualPort)
Claudine Chiu7f872a72016-12-16 13:51:39 -0500696 ));
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800697
698 //Remove all the virtual links connected to this virtual port
699 Set<VirtualLink> existingVirtualLinks = networkIdVirtualLinkSetMap.get(networkId);
700 if (existingVirtualLinks != null && !existingVirtualLinks.isEmpty()) {
701 Set<VirtualLink> virtualLinkSet = new HashSet<>();
702 ConnectPoint cp = new ConnectPoint(deviceId, portNumber);
703 existingVirtualLinks.forEach(virtualLink -> {
704 if (virtualLink.src().equals(cp) || virtualLink.dst().equals(cp)) {
705 virtualLinkSet.add(virtualLink);
706 }
707 });
708 virtualLinkSet.forEach(virtualLink ->
709 removeLink(networkId, virtualLink.src(), virtualLink.dst()));
710 }
711
712 //Remove all the hosts connected to this virtual port
713 Set<HostId> hostIdSet = new HashSet<>();
714 hostIdVirtualHostMap.forEach((hostId, virtualHost) -> {
715 if (virtualHost.location().deviceId().equals(deviceId) &&
716 virtualHost.location().port().equals(portNumber)) {
717 hostIdSet.add(hostId);
718 }
719 });
720 hostIdSet.forEach(hostId -> removeHost(networkId, hostId));
Claudine Chiu7f872a72016-12-16 13:51:39 -0500721 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500722 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700723 }
724
725 @Override
726 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500727 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
728 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
729 if (networkIdSet != null) {
Harold Huange86d35f2017-06-14 15:15:18 +0800730 networkIdSet.forEach(networkId -> {
731 if (networkIdVirtualNetworkMap.get(networkId) != null) {
732 virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId));
733 }
734 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500735 }
736 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700737 }
738
739 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400740 public VirtualNetwork getNetwork(NetworkId networkId) {
741 return networkIdVirtualNetworkMap.get(networkId);
742 }
743
744 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700745 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500746 checkState(networkExists(networkId), "The network has not been added.");
747 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
748 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
749 if (deviceIdSet != null) {
Yoonseon Hanaa256052017-05-08 16:25:38 -0700750 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(
751 deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId))));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500752 }
753 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700754 }
755
756 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400757 public Set<VirtualHost> getHosts(NetworkId networkId) {
758 checkState(networkExists(networkId), "The network has not been added.");
759 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
760 Set<VirtualHost> virtualHostSet = new HashSet<>();
761 if (hostIdSet != null) {
762 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
763 }
764 return ImmutableSet.copyOf(virtualHostSet);
765 }
766
767 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700768 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500769 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500770 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
771 if (virtualLinkSet == null) {
772 virtualLinkSet = new HashSet<>();
773 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500774 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700775 }
776
Brian Stanke612cebf2016-05-02 10:21:33 -0400777 @Override
778 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400779 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
780 if (virtualLinkSet == null) {
781 return null;
782 }
783
784 VirtualLink virtualLink = null;
785 for (VirtualLink link : virtualLinkSet) {
Harold Huang7362e672017-04-19 10:00:11 +0800786 if (src == null && link.dst().equals(dst)) {
787 virtualLink = link;
788 break;
789 } else if (dst == null && link.src().equals(src)) {
790 virtualLink = link;
791 break;
792 } else if (link.src().equals(src) && link.dst().equals(dst)) {
Brian Stanke9a108972016-04-11 15:25:17 -0400793 virtualLink = link;
794 break;
795 }
796 }
797 return virtualLink;
798 }
799
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700800 @Override
801 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500802 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500803 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
804 if (virtualPortSet == null) {
805 virtualPortSet = new HashSet<>();
806 }
807
Brian Stanke612cebf2016-05-02 10:21:33 -0400808 if (deviceId == null) {
809 return ImmutableSet.copyOf(virtualPortSet);
810 }
811
Brian Stanke5df14472016-03-11 19:34:38 -0500812 Set<VirtualPort> portSet = new HashSet<>();
813 virtualPortSet.forEach(virtualPort -> {
814 if (virtualPort.element().id().equals(deviceId)) {
815 portSet.add(virtualPort);
816 }
817 });
818 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500819 }
820
Brian Stanke11f6d532016-07-05 16:17:59 -0400821 @Override
Brian Stanke11f6d532016-07-05 16:17:59 -0400822 public void addTunnelId(Intent intent, TunnelId tunnelId) {
823 // Add the tunnelId to the intent key set map
824 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
825 if (tunnelIdSet == null) {
826 tunnelIdSet = new HashSet<>();
827 }
828 tunnelIdSet.add(tunnelId);
829 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
830 }
831
832 @Override
833 public Set<TunnelId> getTunnelIds(Intent intent) {
834 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
835 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
836 }
837
838 @Override
839 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
840 Set<TunnelId> tunnelIdSet = new HashSet<>();
841 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
842 if (tunnelId1.equals(tunnelId)) {
843 tunnelIdSet.add(tunnelId);
844 }
845 });
846
847 if (!tunnelIdSet.isEmpty()) {
848 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
849 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
850 return new HashSet<>();
851 } else {
852 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
853 }
854 });
855 }
856 }
857
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500858 /**
859 * Listener class to map listener set events to the virtual network events.
860 */
861 private class InternalSetListener implements SetEventListener<TenantId> {
862 @Override
863 public void event(SetEvent<TenantId> event) {
864 VirtualNetworkEvent.Type type = null;
865 switch (event.type()) {
866 case ADD:
867 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
868 break;
869 case REMOVE:
870 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
871 break;
872 default:
873 log.error("Unsupported event type: " + event.type());
874 }
875 notifyDelegate(new VirtualNetworkEvent(type, null));
876 }
877 }
878
879 /**
880 * Listener class to map listener map events to the virtual network events.
881 */
Claudine Chiu945828d2016-11-21 12:47:07 -0500882 private class InternalMapListener<K, V> implements MapEventListener<K, V> {
883
884 private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
885
886 InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
887 this.createEvent = createEvent;
888 }
889
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500890 @Override
Claudine Chiu945828d2016-11-21 12:47:07 -0500891 public void event(MapEvent<K, V> event) {
892 checkNotNull(event.key());
893 VirtualNetworkEvent vnetEvent = null;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500894 switch (event.type()) {
895 case INSERT:
Claudine Chiu945828d2016-11-21 12:47:07 -0500896 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500897 break;
898 case UPDATE:
899 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
Claudine Chiu945828d2016-11-21 12:47:07 -0500900 vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500901 } else {
Claudine Chiu945828d2016-11-21 12:47:07 -0500902 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500903 }
904 break;
905 case REMOVE:
Claudine Chiu945828d2016-11-21 12:47:07 -0500906 if (event.oldValue() != null) {
907 vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
908 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500909 break;
910 default:
911 log.error("Unsupported event type: " + event.type());
912 }
Claudine Chiu945828d2016-11-21 12:47:07 -0500913 if (vnetEvent != null) {
914 notifyDelegate(vnetEvent);
915 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500916 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700917 }
Yoonseon Hanaa256052017-05-08 16:25:38 -0700918
919 /**
920 * A wrapper class to isolate device id from other virtual networks.
921 */
922
923 private static class VirtualDeviceId {
924
925 NetworkId networkId;
926 DeviceId deviceId;
927
928 public VirtualDeviceId(NetworkId networkId, DeviceId deviceId) {
929 this.networkId = networkId;
930 this.deviceId = deviceId;
931 }
932
933 public NetworkId getNetworkId() {
934 return networkId;
935 }
936
937 public DeviceId getDeviceId() {
938 return deviceId;
939 }
940
941 @Override
942 public int hashCode() {
943 return Objects.hash(networkId, deviceId);
944 }
945
946 @Override
947 public boolean equals(Object obj) {
948 if (this == obj) {
949 return true;
950 }
951
952 if (obj instanceof VirtualDeviceId) {
953 VirtualDeviceId that = (VirtualDeviceId) obj;
954 return this.deviceId.equals(that.deviceId) &&
955 this.networkId.equals(that.networkId);
956 }
957 return false;
958 }
959 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700960}