blob: 81a9a3c8a984e059389cbdf4bcf994fe5a92ab85 [file] [log] [blame]
Thomas Vachuska33979fd2015-07-31 11:41:14 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska33979fd2015-07-31 11:41:14 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.incubator.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;
58import org.onosproject.net.intent.IntentData;
59import org.onosproject.net.intent.IntentState;
60import org.onosproject.net.intent.Key;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070061import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050062import org.onosproject.store.serializers.KryoNamespaces;
63import org.onosproject.store.service.ConsistentMap;
64import org.onosproject.store.service.DistributedSet;
65import org.onosproject.store.service.MapEvent;
66import org.onosproject.store.service.MapEventListener;
67import org.onosproject.store.service.Serializer;
68import org.onosproject.store.service.SetEvent;
69import org.onosproject.store.service.SetEventListener;
70import org.onosproject.store.service.StorageService;
Brian Stanke11f6d532016-07-05 16:17:59 -040071import org.onosproject.store.service.WallClockTimestamp;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072import org.slf4j.Logger;
73
Brian Stanke0e5c94e2016-03-08 11:20:04 -050074import java.util.HashSet;
75import java.util.Map;
Harold Huangb7d6b8e2017-04-03 17:13:33 +080076import java.util.Optional;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070077import java.util.Set;
Claudine Chiu7f872a72016-12-16 13:51:39 -050078import java.util.concurrent.atomic.AtomicBoolean;
Claudine Chiu945828d2016-11-21 12:47:07 -050079import java.util.function.BiFunction;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070080
Brian Stanke0e5c94e2016-03-08 11:20:04 -050081import static com.google.common.base.Preconditions.checkNotNull;
82import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070083import static org.slf4j.LoggerFactory.getLogger;
84
85/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050086 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070087 */
88@Component(immediate = true)
89@Service
90public class DistributedVirtualNetworkStore
91 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
92 implements VirtualNetworkStore {
93
94 private final Logger log = getLogger(getClass());
95
Brian Stanke0e5c94e2016-03-08 11:20:04 -050096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070098
Brian Stanke0e5c94e2016-03-08 11:20:04 -050099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700101
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500102 private IdGenerator idGenerator;
103
104 // Track tenants by ID
105 private DistributedSet<TenantId> tenantIdSet;
106
107 // Listener for tenant events
108 private final SetEventListener<TenantId> setListener = new InternalSetListener();
109
110 // Track virtual networks by network Id
111 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
112 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
113
114 // Listener for virtual network events
Claudine Chiu945828d2016-11-21 12:47:07 -0500115 private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
116 new InternalMapListener<>((mapEventType, virtualNetwork) -> {
117 VirtualNetworkEvent.Type eventType =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900118 mapEventType.equals(MapEvent.Type.INSERT)
119 ? VirtualNetworkEvent.Type.NETWORK_ADDED :
120 mapEventType.equals(MapEvent.Type.UPDATE)
121 ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
122 mapEventType.equals(MapEvent.Type.REMOVE)
123 ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
Claudine Chiu945828d2016-11-21 12:47:07 -0500124 return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
125 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500126
sangyun-han3c3e99e2017-02-08 15:30:53 +0900127 // Listener for virtual device events
128 private final MapEventListener<DeviceId, VirtualDevice> virtualDeviceMapListener =
129 new InternalMapListener<>((mapEventType, virtualDevice) -> {
130 VirtualNetworkEvent.Type eventType =
131 mapEventType.equals(MapEvent.Type.INSERT)
132 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
133 mapEventType.equals(MapEvent.Type.UPDATE)
134 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
135 mapEventType.equals(MapEvent.Type.REMOVE)
136 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
137 return eventType == null ? null :
138 new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
139 });
140
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500141 // Track virtual network IDs by tenant Id
142 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
143 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
144
145 // Track virtual devices by device Id
146 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
147 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
148
149 // Track device IDs by network Id
150 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
151 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
152
Brian Stanke7a81b532016-06-14 15:43:51 -0400153 // Track virtual hosts by host Id
154 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
155 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
156
157 // Track host IDs by network Id
158 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
159 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
160
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500161 // Track virtual links by network Id
162 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
163 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
164
165 // Track virtual ports by network Id
166 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
167 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
168
Brian Stanke11f6d532016-07-05 16:17:59 -0400169 // Track intent key to intent data
170 private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
171 private Map<Key, IntentData> intentKeyIntentDataMap;
172
173 // Track intent ID to TunnelIds
174 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
175 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
176
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500177 private static final Serializer SERIALIZER = Serializer
178 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
179 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700180 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500181 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500182 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500183 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500184 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400185 .register(VirtualHost.class)
186 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500187 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500188 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500189 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500190 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500191 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400192 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400193 .register(IntentData.class)
194 .register(VirtualNetworkIntent.class)
195 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700196 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400197 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500198
199 /**
200 * Distributed network store service activate method.
201 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700202 @Activate
203 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500204 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
205
206 tenantIdSet = storageService.<TenantId>setBuilder()
207 .withSerializer(SERIALIZER)
208 .withName("onos-tenantId")
209 .withRelaxedReadConsistency()
210 .build()
211 .asDistributedSet();
212 tenantIdSet.addListener(setListener);
213
214 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
215 .withSerializer(SERIALIZER)
216 .withName("onos-networkId-virtualnetwork")
217 .withRelaxedReadConsistency()
218 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500219 networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500220 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
221
222 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
223 .withSerializer(SERIALIZER)
224 .withName("onos-tenantId-networkIds")
225 .withRelaxedReadConsistency()
226 .build();
227 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
228
229 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
230 .withSerializer(SERIALIZER)
231 .withName("onos-deviceId-virtualdevice")
232 .withRelaxedReadConsistency()
233 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500234 deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500235 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
236
237 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
238 .withSerializer(SERIALIZER)
239 .withName("onos-networkId-deviceIds")
240 .withRelaxedReadConsistency()
241 .build();
242 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
243
Brian Stanke7a81b532016-06-14 15:43:51 -0400244 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
245 .withSerializer(SERIALIZER)
246 .withName("onos-hostId-virtualhost")
247 .withRelaxedReadConsistency()
248 .build();
249 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
250
251 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
252 .withSerializer(SERIALIZER)
253 .withName("onos-networkId-hostIds")
254 .withRelaxedReadConsistency()
255 .build();
256 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
257
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500258 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
259 .withSerializer(SERIALIZER)
260 .withName("onos-networkId-virtuallinks")
261 .withRelaxedReadConsistency()
262 .build();
263 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
264
265 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
266 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400267 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500268 .withRelaxedReadConsistency()
269 .build();
270 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
271
Brian Stanke11f6d532016-07-05 16:17:59 -0400272 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
273 .withSerializer(SERIALIZER)
274 .withName("onos-intentKey-tunnelIds")
275 .withRelaxedReadConsistency()
276 .build();
277 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
278
279 intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
280 .withSerializer(SERIALIZER)
281 .withName("onos-intentKey-intentData")
282 .withRelaxedReadConsistency()
283 .build();
284 intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
285
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700286 log.info("Started");
287 }
288
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500289 /**
290 * Distributed network store service deactivate method.
291 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700292 @Deactivate
293 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500294 tenantIdSet.removeListener(setListener);
Claudine Chiu945828d2016-11-21 12:47:07 -0500295 networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
296 deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700297 log.info("Stopped");
298 }
299
300 @Override
301 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500302 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700303 }
304
305 @Override
306 public void removeTenantId(TenantId tenantId) {
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800307 //Remove all the virtual networks of this tenant
308 Set<VirtualNetwork> networkIdSet = getNetworks(tenantId);
309 if (networkIdSet != null) {
310 networkIdSet.forEach(virtualNetwork -> removeNetwork(virtualNetwork.id()));
311 }
312
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500313 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700314 }
315
316 @Override
317 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500318 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700319 }
320
321 @Override
322 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500323
324 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
325 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
326 //TODO update both maps in one transaction.
327 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500328
329 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
330 if (networkIdSet == null) {
331 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500332 }
Brian Stanke5df14472016-03-11 19:34:38 -0500333 networkIdSet.add(virtualNetwork.id());
334 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
335
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500336 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700337 }
338
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500339 /**
340 * Returns a new network identifier from a virtual network block of identifiers.
341 *
342 * @return NetworkId network identifier
343 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700344 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900345 NetworkId networkId;
346 do {
347 networkId = NetworkId.networkId(idGenerator.getNewId());
348 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700349
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900350 return networkId;
351 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700352
353 @Override
354 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500355 // Make sure that the virtual network exists before attempting to remove it.
356 if (networkExists(networkId)) {
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800357 //Remove all the devices of this network
358 Set<VirtualDevice> deviceSet = getDevices(networkId);
359 if (deviceSet != null) {
360 deviceSet.forEach(virtualDevice -> removeDevice(networkId, virtualDevice.id()));
361 }
Brian Stanke5df14472016-03-11 19:34:38 -0500362 //TODO update both maps in one transaction.
363
364 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500365 if (virtualNetwork == null) {
366 return;
367 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500368 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500369
Brian Stanke5df14472016-03-11 19:34:38 -0500370 Set<NetworkId> networkIdSet = new HashSet<>();
371 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
372 if (networkId1.id().equals(networkId.id())) {
373 networkIdSet.add(networkId1);
374 }
375 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500376
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500377 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
378 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700379 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500380 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700381 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500382 }
383 });
384 }
385 }
386
387 /**
388 * Returns if the network identifier exists.
389 *
390 * @param networkId network identifier
391 * @return true if the network identifier exists, false otherwise.
392 */
393 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400394 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500395 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700396 }
397
398 @Override
399 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500400 checkState(networkExists(networkId), "The network has not been added.");
401 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
402 if (deviceIdSet == null) {
403 deviceIdSet = new HashSet<>();
404 }
405 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
406 //TODO update both maps in one transaction.
407 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
408 deviceIdSet.add(deviceId);
409 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
410 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700411 }
412
413 @Override
414 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500415 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800416 //Remove all the virtual ports of the this device
417 Set<VirtualPort> virtualPorts = getPorts(networkId, deviceId);
418 if (virtualPorts != null) {
419 virtualPorts.forEach(virtualPort -> removePort(networkId, deviceId, virtualPort.number()));
420 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500421 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500422
423 Set<DeviceId> deviceIdSet = new HashSet<>();
424 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
425 if (deviceId1.equals(deviceId)) {
426 deviceIdSet.add(deviceId1);
427 }
428 });
429
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500430 if (deviceIdSet != null) {
431 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
432 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700433 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500434 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700435 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500436 }
437 });
438
Brian Stanke5df14472016-03-11 19:34:38 -0500439 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500440 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400441 }
442
443 @Override
444 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
445 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
446 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800447 checkState(virtualPortExists(networkId, location.deviceId(), location.port()),
448 "The virtual port has not been created.");
Brian Stanke7a81b532016-06-14 15:43:51 -0400449 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
450 if (hostIdSet == null) {
451 hostIdSet = new HashSet<>();
452 }
453 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
454 //TODO update both maps in one transaction.
455 hostIdVirtualHostMap.put(hostId, virtualhost);
456 hostIdSet.add(hostId);
457 networkIdHostIdSetMap.put(networkId, hostIdSet);
458 return virtualhost;
459 }
460
461 @Override
462 public void removeHost(NetworkId networkId, HostId hostId) {
463 checkState(networkExists(networkId), "The network has not been added.");
464 //TODO update both maps in one transaction.
465
466 Set<HostId> hostIdSet = new HashSet<>();
467 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
468 if (hostId1.equals(hostId)) {
469 hostIdSet.add(hostId1);
470 }
471 });
472
473 if (hostIdSet != null) {
474 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
475 if (existingHostIds == null || existingHostIds.isEmpty()) {
476 return new HashSet<>();
477 } else {
478 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
479 }
480 });
481
482 hostIdVirtualHostMap.remove(hostId);
483 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700484 }
485
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800486 /**
487 * Returns if the given virtual port exists.
488 *
489 * @param networkId network identifier
490 * @param deviceId virtual device Id
491 * @param portNumber virtual port number
492 * @return true if the virtual port exists, false otherwise.
493 */
494 private boolean virtualPortExists(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
495 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
496 if (virtualPortSet != null) {
497 return virtualPortSet.stream().anyMatch(
498 p -> p.element().id().equals(deviceId) &&
499 p.number().equals(portNumber));
500 } else {
501 return false;
502 }
503 }
504
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700505 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400506 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
507 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500508 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800509 checkState(virtualPortExists(networkId, src.deviceId(), src.port()),
510 "The source virtual port has not been added.");
511 checkState(virtualPortExists(networkId, dst.deviceId(), dst.port()),
512 "The destination virtual port has not been added.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500513 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
514 if (virtualLinkSet == null) {
515 virtualLinkSet = new HashSet<>();
516 }
Harold Huang7362e672017-04-19 10:00:11 +0800517
Brian Stanke9a108972016-04-11 15:25:17 -0400518 // validate that the link does not already exist in this network
Harold Huang7362e672017-04-19 10:00:11 +0800519 checkState(getLink(networkId, src, dst) == null,
520 "The virtual link already exists");
521 checkState(getLink(networkId, src, null) == null,
522 "The source connection point has been used by another link");
523 checkState(getLink(networkId, null, dst) == null,
524 "The destination connection point has been used by another link");
Brian Stanke9a108972016-04-11 15:25:17 -0400525
526 VirtualLink virtualLink = DefaultVirtualLink.builder()
527 .networkId(networkId)
528 .src(src)
529 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400530 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400531 .tunnelId(realizedBy)
532 .build();
533
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500534 virtualLinkSet.add(virtualLink);
535 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
536 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700537 }
538
539 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400540 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400541 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
542 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
543 if (virtualLinkSet == null) {
544 virtualLinkSet = new HashSet<>();
Harold Huang7362e672017-04-19 10:00:11 +0800545 networkIdVirtualLinkSetMap.put(virtualLink.networkId(), virtualLinkSet);
546 log.warn("The updated virtual link {} has not been added", virtualLink);
547 return;
Brian Stanke9a108972016-04-11 15:25:17 -0400548 }
Harold Huang7362e672017-04-19 10:00:11 +0800549 if (!virtualLinkSet.remove(virtualLink)) {
550 log.warn("The updated virtual link {} does not exist", virtualLink);
551 return;
552 }
Brian Stanke9a108972016-04-11 15:25:17 -0400553
554 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
555 .networkId(virtualLink.networkId())
556 .src(virtualLink.src())
557 .dst(virtualLink.dst())
558 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400559 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400560 .build();
561
562 virtualLinkSet.add(newVirtualLink);
563 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
564 }
565
566 @Override
567 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500568 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500569
Brian Stanke9a108972016-04-11 15:25:17 -0400570 final VirtualLink virtualLink = getLink(networkId, src, dst);
571 if (virtualLink == null) {
Harold Huang7362e672017-04-19 10:00:11 +0800572 log.warn("The removed virtual link between {} and {} does not exist", src, dst);
Brian Stanke9a108972016-04-11 15:25:17 -0400573 return null;
574 }
Brian Stanke5df14472016-03-11 19:34:38 -0500575 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400576 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500577
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500578 if (virtualLinkSet != null) {
579 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
580 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700581 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500582 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700583 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500584 }
585 });
586 }
Brian Stanke9a108972016-04-11 15:25:17 -0400587 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700588 }
589
590 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700591 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
592 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500593 checkState(networkExists(networkId), "The network has not been added.");
594 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700595
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500596 if (virtualPortSet == null) {
597 virtualPortSet = new HashSet<>();
598 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700599
Claudine Chiu465a2602017-03-17 18:33:36 -0400600 VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500601 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700602
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800603 checkState(!virtualPortExists(networkId, deviceId, portNumber),
604 "The requested Port Number has been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700605
606 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
607 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500608 virtualPortSet.add(virtualPort);
609 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500610 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400611 networkId, device, virtualPort));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500612 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700613 }
614
615 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700616 public void bindPort(NetworkId networkId, DeviceId deviceId,
617 PortNumber portNumber, ConnectPoint realizedBy) {
618
619 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
620 .get(networkId);
621
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800622 Optional<VirtualPort> virtualPortOptional = virtualPortSet.stream().filter(
Yoonseon Han6c603892016-09-01 11:52:21 -0700623 p -> p.element().id().equals(deviceId) &&
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800624 p.number().equals(portNumber)).findFirst();
625 checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700626
Claudine Chiu465a2602017-03-17 18:33:36 -0400627 VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700628 checkNotNull(device, "The device has not been created for deviceId: "
629 + deviceId);
630
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800631 VirtualPort vPort = virtualPortOptional.get();
Yoonseon Han6c603892016-09-01 11:52:21 -0700632 virtualPortSet.remove(vPort);
633 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
634 virtualPortSet.add(vPort);
635 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500636 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400637 networkId, device, vPort));
Yoonseon Han6c603892016-09-01 11:52:21 -0700638 }
639
640 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700641 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500642 checkState(networkExists(networkId), "The network has not been added.");
Claudine Chiu465a2602017-03-17 18:33:36 -0400643 VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
644 checkNotNull(device, "The device has not been created for deviceId: "
645 + deviceId);
Brian Stanke5df14472016-03-11 19:34:38 -0500646
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800647 if (networkIdVirtualPortSetMap.get(networkId) == null) {
648 log.warn("No port has been created for NetworkId: {}", networkId);
649 return;
650 }
651
Brian Stanke5df14472016-03-11 19:34:38 -0500652 Set<VirtualPort> virtualPortSet = new HashSet<>();
653 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
654 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
655 virtualPortSet.add(port);
656 }
657 });
658
Claudine Chiu7f872a72016-12-16 13:51:39 -0500659 if (!virtualPortSet.isEmpty()) {
660 AtomicBoolean portRemoved = new AtomicBoolean(false);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500661 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
662 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700663 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500664 } else {
Claudine Chiu7f872a72016-12-16 13:51:39 -0500665 portRemoved.set(true);
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700666 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500667 }
668 });
Claudine Chiu7f872a72016-12-16 13:51:39 -0500669 if (portRemoved.get()) {
670 virtualPortSet.forEach(virtualPort -> notifyDelegate(
671 new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400672 networkId, device, virtualPort)
Claudine Chiu7f872a72016-12-16 13:51:39 -0500673 ));
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800674
675 //Remove all the virtual links connected to this virtual port
676 Set<VirtualLink> existingVirtualLinks = networkIdVirtualLinkSetMap.get(networkId);
677 if (existingVirtualLinks != null && !existingVirtualLinks.isEmpty()) {
678 Set<VirtualLink> virtualLinkSet = new HashSet<>();
679 ConnectPoint cp = new ConnectPoint(deviceId, portNumber);
680 existingVirtualLinks.forEach(virtualLink -> {
681 if (virtualLink.src().equals(cp) || virtualLink.dst().equals(cp)) {
682 virtualLinkSet.add(virtualLink);
683 }
684 });
685 virtualLinkSet.forEach(virtualLink ->
686 removeLink(networkId, virtualLink.src(), virtualLink.dst()));
687 }
688
689 //Remove all the hosts connected to this virtual port
690 Set<HostId> hostIdSet = new HashSet<>();
691 hostIdVirtualHostMap.forEach((hostId, virtualHost) -> {
692 if (virtualHost.location().deviceId().equals(deviceId) &&
693 virtualHost.location().port().equals(portNumber)) {
694 hostIdSet.add(hostId);
695 }
696 });
697 hostIdSet.forEach(hostId -> removeHost(networkId, hostId));
Claudine Chiu7f872a72016-12-16 13:51:39 -0500698 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500699 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700700 }
701
702 @Override
703 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500704 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
705 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
706 if (networkIdSet != null) {
707 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
708 }
709 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700710 }
711
712 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400713 public VirtualNetwork getNetwork(NetworkId networkId) {
714 return networkIdVirtualNetworkMap.get(networkId);
715 }
716
717 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700718 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500719 checkState(networkExists(networkId), "The network has not been added.");
720 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
721 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
722 if (deviceIdSet != null) {
723 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
724 }
725 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700726 }
727
728 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400729 public Set<VirtualHost> getHosts(NetworkId networkId) {
730 checkState(networkExists(networkId), "The network has not been added.");
731 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
732 Set<VirtualHost> virtualHostSet = new HashSet<>();
733 if (hostIdSet != null) {
734 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
735 }
736 return ImmutableSet.copyOf(virtualHostSet);
737 }
738
739 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700740 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500741 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500742 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
743 if (virtualLinkSet == null) {
744 virtualLinkSet = new HashSet<>();
745 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500746 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700747 }
748
Brian Stanke612cebf2016-05-02 10:21:33 -0400749 @Override
750 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400751 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
752 if (virtualLinkSet == null) {
753 return null;
754 }
755
756 VirtualLink virtualLink = null;
757 for (VirtualLink link : virtualLinkSet) {
Harold Huang7362e672017-04-19 10:00:11 +0800758 if (src == null && link.dst().equals(dst)) {
759 virtualLink = link;
760 break;
761 } else if (dst == null && link.src().equals(src)) {
762 virtualLink = link;
763 break;
764 } else if (link.src().equals(src) && link.dst().equals(dst)) {
Brian Stanke9a108972016-04-11 15:25:17 -0400765 virtualLink = link;
766 break;
767 }
768 }
769 return virtualLink;
770 }
771
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700772 @Override
773 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500774 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500775 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
776 if (virtualPortSet == null) {
777 virtualPortSet = new HashSet<>();
778 }
779
Brian Stanke612cebf2016-05-02 10:21:33 -0400780 if (deviceId == null) {
781 return ImmutableSet.copyOf(virtualPortSet);
782 }
783
Brian Stanke5df14472016-03-11 19:34:38 -0500784 Set<VirtualPort> portSet = new HashSet<>();
785 virtualPortSet.forEach(virtualPort -> {
786 if (virtualPort.element().id().equals(deviceId)) {
787 portSet.add(virtualPort);
788 }
789 });
790 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500791 }
792
Brian Stanke11f6d532016-07-05 16:17:59 -0400793 @Override
794 public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
795 checkNotNull(intent, "Intent cannot be null");
796 IntentData intentData = removeIntent(intent.key());
797 if (intentData == null) {
798 intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
799 } else {
800 intentData = new IntentData(intent, state, intentData.version());
801 }
802 intentKeyIntentDataMap.put(intent.key(), intentData);
803 }
804
805 @Override
806 public IntentData removeIntent(Key intentKey) {
807 checkNotNull(intentKey, "Intent key cannot be null");
808 return intentKeyIntentDataMap.remove(intentKey);
809 }
810
811 @Override
812 public void addTunnelId(Intent intent, TunnelId tunnelId) {
813 // Add the tunnelId to the intent key set map
814 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
815 if (tunnelIdSet == null) {
816 tunnelIdSet = new HashSet<>();
817 }
818 tunnelIdSet.add(tunnelId);
819 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
820 }
821
822 @Override
823 public Set<TunnelId> getTunnelIds(Intent intent) {
824 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
825 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
826 }
827
828 @Override
829 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
830 Set<TunnelId> tunnelIdSet = new HashSet<>();
831 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
832 if (tunnelId1.equals(tunnelId)) {
833 tunnelIdSet.add(tunnelId);
834 }
835 });
836
837 if (!tunnelIdSet.isEmpty()) {
838 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
839 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
840 return new HashSet<>();
841 } else {
842 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
843 }
844 });
845 }
846 }
847
848 @Override
849 public Set<Intent> getIntents() {
850 Set<Intent> intents = new HashSet<>();
851 intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
852 return ImmutableSet.copyOf(intents);
853 }
854
855 @Override
856 public Intent getIntent(Key key) {
857 IntentData intentData = intentKeyIntentDataMap.get(key);
858 return intentData == null ? null : intentData.intent();
859 }
860
861 @Override
862 public Set<IntentData> getIntentData() {
863 return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
864 }
865
866 @Override
867 public IntentData getIntentData(Key key) {
868 IntentData intentData = intentKeyIntentDataMap.get(key);
869 return intentData == null ? null : new IntentData(intentData);
870 }
871
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500872 /**
873 * Listener class to map listener set events to the virtual network events.
874 */
875 private class InternalSetListener implements SetEventListener<TenantId> {
876 @Override
877 public void event(SetEvent<TenantId> event) {
878 VirtualNetworkEvent.Type type = null;
879 switch (event.type()) {
880 case ADD:
881 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
882 break;
883 case REMOVE:
884 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
885 break;
886 default:
887 log.error("Unsupported event type: " + event.type());
888 }
889 notifyDelegate(new VirtualNetworkEvent(type, null));
890 }
891 }
892
893 /**
894 * Listener class to map listener map events to the virtual network events.
895 */
Claudine Chiu945828d2016-11-21 12:47:07 -0500896 private class InternalMapListener<K, V> implements MapEventListener<K, V> {
897
898 private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
899
900 InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
901 this.createEvent = createEvent;
902 }
903
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500904 @Override
Claudine Chiu945828d2016-11-21 12:47:07 -0500905 public void event(MapEvent<K, V> event) {
906 checkNotNull(event.key());
907 VirtualNetworkEvent vnetEvent = null;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500908 switch (event.type()) {
909 case INSERT:
Claudine Chiu945828d2016-11-21 12:47:07 -0500910 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500911 break;
912 case UPDATE:
913 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
Claudine Chiu945828d2016-11-21 12:47:07 -0500914 vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500915 } else {
Claudine Chiu945828d2016-11-21 12:47:07 -0500916 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500917 }
918 break;
919 case REMOVE:
Claudine Chiu945828d2016-11-21 12:47:07 -0500920 if (event.oldValue() != null) {
921 vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
922 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500923 break;
924 default:
925 log.error("Unsupported event type: " + event.type());
926 }
Claudine Chiu945828d2016-11-21 12:47:07 -0500927 if (vnetEvent != null) {
928 notifyDelegate(vnetEvent);
929 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500930 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700931 }
932}