blob: 64479164a4470be29e5a7bf23a7c9e502423a64f [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;
Yoonseon Hanaa256052017-05-08 16:25:38 -070076import java.util.Objects;
Harold Huangb7d6b8e2017-04-03 17:13:33 +080077import java.util.Optional;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070078import java.util.Set;
Claudine Chiu7f872a72016-12-16 13:51:39 -050079import java.util.concurrent.atomic.AtomicBoolean;
Claudine Chiu945828d2016-11-21 12:47:07 -050080import java.util.function.BiFunction;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070081
Brian Stanke0e5c94e2016-03-08 11:20:04 -050082import static com.google.common.base.Preconditions.checkNotNull;
83import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070084import static org.slf4j.LoggerFactory.getLogger;
85
86/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050087 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070088 */
89@Component(immediate = true)
90@Service
91public class DistributedVirtualNetworkStore
92 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
93 implements VirtualNetworkStore {
94
95 private final Logger log = getLogger(getClass());
96
Brian Stanke0e5c94e2016-03-08 11:20:04 -050097 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070099
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700102
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500103 private IdGenerator idGenerator;
104
105 // Track tenants by ID
106 private DistributedSet<TenantId> tenantIdSet;
107
108 // Listener for tenant events
109 private final SetEventListener<TenantId> setListener = new InternalSetListener();
110
111 // Track virtual networks by network Id
112 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
113 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
114
115 // Listener for virtual network events
Claudine Chiu945828d2016-11-21 12:47:07 -0500116 private final MapEventListener<NetworkId, VirtualNetwork> virtualNetworkMapListener =
117 new InternalMapListener<>((mapEventType, virtualNetwork) -> {
118 VirtualNetworkEvent.Type eventType =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900119 mapEventType.equals(MapEvent.Type.INSERT)
120 ? VirtualNetworkEvent.Type.NETWORK_ADDED :
121 mapEventType.equals(MapEvent.Type.UPDATE)
122 ? VirtualNetworkEvent.Type.NETWORK_UPDATED :
123 mapEventType.equals(MapEvent.Type.REMOVE)
124 ? VirtualNetworkEvent.Type.NETWORK_REMOVED : null;
Claudine Chiu945828d2016-11-21 12:47:07 -0500125 return eventType == null ? null : new VirtualNetworkEvent(eventType, virtualNetwork.id());
126 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500127
sangyun-han3c3e99e2017-02-08 15:30:53 +0900128 // Listener for virtual device events
Yoonseon Hanaa256052017-05-08 16:25:38 -0700129 private final MapEventListener<VirtualDeviceId, VirtualDevice> virtualDeviceMapListener =
sangyun-han3c3e99e2017-02-08 15:30:53 +0900130 new InternalMapListener<>((mapEventType, virtualDevice) -> {
131 VirtualNetworkEvent.Type eventType =
132 mapEventType.equals(MapEvent.Type.INSERT)
133 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_ADDED :
134 mapEventType.equals(MapEvent.Type.UPDATE)
135 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_UPDATED :
136 mapEventType.equals(MapEvent.Type.REMOVE)
137 ? VirtualNetworkEvent.Type.VIRTUAL_DEVICE_REMOVED : null;
138 return eventType == null ? null :
139 new VirtualNetworkEvent(eventType, virtualDevice.networkId(), virtualDevice);
140 });
141
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500142 // Track virtual network IDs by tenant Id
143 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
144 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
145
146 // Track virtual devices by device Id
Yoonseon Hanaa256052017-05-08 16:25:38 -0700147 private ConsistentMap<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
148 private Map<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500149
150 // Track device IDs by network Id
151 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
152 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
153
Brian Stanke7a81b532016-06-14 15:43:51 -0400154 // Track virtual hosts by host Id
155 private ConsistentMap<HostId, VirtualHost> hostIdVirtualHostConsistentMap;
156 private Map<HostId, VirtualHost> hostIdVirtualHostMap;
157
158 // Track host IDs by network Id
159 private ConsistentMap<NetworkId, Set<HostId>> networkIdHostIdSetConsistentMap;
160 private Map<NetworkId, Set<HostId>> networkIdHostIdSetMap;
161
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500162 // Track virtual links by network Id
163 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
164 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
165
166 // Track virtual ports by network Id
167 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
168 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
169
Brian Stanke11f6d532016-07-05 16:17:59 -0400170 // Track intent key to intent data
171 private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap;
172 private Map<Key, IntentData> intentKeyIntentDataMap;
173
174 // Track intent ID to TunnelIds
175 private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap;
176 private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap;
177
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500178 private static final Serializer SERIALIZER = Serializer
179 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
180 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700181 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500182 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500183 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500184 .register(VirtualDevice.class)
Yoonseon Hanaa256052017-05-08 16:25:38 -0700185 .register(VirtualDeviceId.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500186 .register(DefaultVirtualDevice.class)
Brian Stanke7a81b532016-06-14 15:43:51 -0400187 .register(VirtualHost.class)
188 .register(DefaultVirtualHost.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500189 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500190 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500191 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500192 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500193 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400194 .register(TunnelId.class)
Brian Stanke11f6d532016-07-05 16:17:59 -0400195 .register(IntentData.class)
196 .register(VirtualNetworkIntent.class)
197 .register(WallClockTimestamp.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700198 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
Brian Stanke11f6d532016-07-05 16:17:59 -0400199 .build());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500200
201 /**
202 * Distributed network store service activate method.
203 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700204 @Activate
205 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500206 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
207
208 tenantIdSet = storageService.<TenantId>setBuilder()
209 .withSerializer(SERIALIZER)
210 .withName("onos-tenantId")
211 .withRelaxedReadConsistency()
212 .build()
213 .asDistributedSet();
214 tenantIdSet.addListener(setListener);
215
216 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
217 .withSerializer(SERIALIZER)
218 .withName("onos-networkId-virtualnetwork")
219 .withRelaxedReadConsistency()
220 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500221 networkIdVirtualNetworkConsistentMap.addListener(virtualNetworkMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500222 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
223
224 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
225 .withSerializer(SERIALIZER)
226 .withName("onos-tenantId-networkIds")
227 .withRelaxedReadConsistency()
228 .build();
229 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
230
Yoonseon Hanaa256052017-05-08 16:25:38 -0700231 deviceIdVirtualDeviceConsistentMap = storageService.<VirtualDeviceId, VirtualDevice>consistentMapBuilder()
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500232 .withSerializer(SERIALIZER)
233 .withName("onos-deviceId-virtualdevice")
234 .withRelaxedReadConsistency()
235 .build();
Claudine Chiu945828d2016-11-21 12:47:07 -0500236 deviceIdVirtualDeviceConsistentMap.addListener(virtualDeviceMapListener);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500237 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
238
239 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
240 .withSerializer(SERIALIZER)
241 .withName("onos-networkId-deviceIds")
242 .withRelaxedReadConsistency()
243 .build();
244 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
245
Brian Stanke7a81b532016-06-14 15:43:51 -0400246 hostIdVirtualHostConsistentMap = storageService.<HostId, VirtualHost>consistentMapBuilder()
247 .withSerializer(SERIALIZER)
248 .withName("onos-hostId-virtualhost")
249 .withRelaxedReadConsistency()
250 .build();
251 hostIdVirtualHostMap = hostIdVirtualHostConsistentMap.asJavaMap();
252
253 networkIdHostIdSetConsistentMap = storageService.<NetworkId, Set<HostId>>consistentMapBuilder()
254 .withSerializer(SERIALIZER)
255 .withName("onos-networkId-hostIds")
256 .withRelaxedReadConsistency()
257 .build();
258 networkIdHostIdSetMap = networkIdHostIdSetConsistentMap.asJavaMap();
259
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500260 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
261 .withSerializer(SERIALIZER)
262 .withName("onos-networkId-virtuallinks")
263 .withRelaxedReadConsistency()
264 .build();
265 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
266
267 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
268 .withSerializer(SERIALIZER)
Brian Stanke11f6d532016-07-05 16:17:59 -0400269 .withName("onos-networkId-virtualports")
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500270 .withRelaxedReadConsistency()
271 .build();
272 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
273
Brian Stanke11f6d532016-07-05 16:17:59 -0400274 intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder()
275 .withSerializer(SERIALIZER)
276 .withName("onos-intentKey-tunnelIds")
277 .withRelaxedReadConsistency()
278 .build();
279 intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap();
280
281 intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder()
282 .withSerializer(SERIALIZER)
283 .withName("onos-intentKey-intentData")
284 .withRelaxedReadConsistency()
285 .build();
286 intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap();
287
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700288 log.info("Started");
289 }
290
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500291 /**
292 * Distributed network store service deactivate method.
293 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700294 @Deactivate
295 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500296 tenantIdSet.removeListener(setListener);
Claudine Chiu945828d2016-11-21 12:47:07 -0500297 networkIdVirtualNetworkConsistentMap.removeListener(virtualNetworkMapListener);
298 deviceIdVirtualDeviceConsistentMap.removeListener(virtualDeviceMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700299 log.info("Stopped");
300 }
301
302 @Override
303 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500304 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700305 }
306
307 @Override
308 public void removeTenantId(TenantId tenantId) {
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800309 //Remove all the virtual networks of this tenant
310 Set<VirtualNetwork> networkIdSet = getNetworks(tenantId);
311 if (networkIdSet != null) {
312 networkIdSet.forEach(virtualNetwork -> removeNetwork(virtualNetwork.id()));
313 }
314
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500315 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700316 }
317
318 @Override
319 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500320 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700321 }
322
323 @Override
324 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500325
326 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
327 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
328 //TODO update both maps in one transaction.
329 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500330
331 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
332 if (networkIdSet == null) {
333 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500334 }
Brian Stanke5df14472016-03-11 19:34:38 -0500335 networkIdSet.add(virtualNetwork.id());
336 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
337
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500338 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700339 }
340
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500341 /**
342 * Returns a new network identifier from a virtual network block of identifiers.
343 *
344 * @return NetworkId network identifier
345 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700346 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900347 NetworkId networkId;
348 do {
349 networkId = NetworkId.networkId(idGenerator.getNewId());
350 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700351
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900352 return networkId;
353 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700354
355 @Override
356 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500357 // Make sure that the virtual network exists before attempting to remove it.
Claudine Chiu70e2db82017-05-04 09:53:11 -0400358 checkState(networkExists(networkId), "The network does not exist.");
Brian Stanke5df14472016-03-11 19:34:38 -0500359
Claudine Chiu70e2db82017-05-04 09:53:11 -0400360 //Remove all the devices of this network
361 Set<VirtualDevice> deviceSet = getDevices(networkId);
362 if (deviceSet != null) {
363 deviceSet.forEach(virtualDevice -> removeDevice(networkId, virtualDevice.id()));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500364 }
Claudine Chiu70e2db82017-05-04 09:53:11 -0400365 //TODO update both maps in one transaction.
366
367 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
368 if (virtualNetwork == null) {
369 return;
370 }
371 TenantId tenantId = virtualNetwork.tenantId();
372
373 Set<NetworkId> networkIdSet = new HashSet<>();
374 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
375 if (networkId1.id().equals(networkId.id())) {
376 networkIdSet.add(networkId1);
377 }
378 });
379
380 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
381 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
382 return new HashSet<>();
383 } else {
384 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
385 }
386 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500387 }
388
389 /**
390 * Returns if the network identifier exists.
391 *
392 * @param networkId network identifier
393 * @return true if the network identifier exists, false otherwise.
394 */
395 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400396 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500397 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700398 }
399
400 @Override
401 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500402 checkState(networkExists(networkId), "The network has not been added.");
Yoonseon Hanaa256052017-05-08 16:25:38 -0700403
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500404 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
405 if (deviceIdSet == null) {
406 deviceIdSet = new HashSet<>();
407 }
Yoonseon Hanaa256052017-05-08 16:25:38 -0700408
409 checkState(!deviceIdSet.contains(deviceId), "The device already exists.");
410
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500411 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
412 //TODO update both maps in one transaction.
Yoonseon Hanaa256052017-05-08 16:25:38 -0700413 deviceIdVirtualDeviceMap.put(new VirtualDeviceId(networkId, deviceId), virtualDevice);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500414 deviceIdSet.add(deviceId);
415 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
416 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700417 }
418
419 @Override
420 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500421 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800422 //Remove all the virtual ports of the this device
423 Set<VirtualPort> virtualPorts = getPorts(networkId, deviceId);
424 if (virtualPorts != null) {
425 virtualPorts.forEach(virtualPort -> removePort(networkId, deviceId, virtualPort.number()));
426 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500427 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500428
429 Set<DeviceId> deviceIdSet = new HashSet<>();
430 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
431 if (deviceId1.equals(deviceId)) {
432 deviceIdSet.add(deviceId1);
433 }
434 });
435
Yoonseon Hanaa256052017-05-08 16:25:38 -0700436 if (!deviceIdSet.isEmpty()) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500437 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
438 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700439 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500440 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700441 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500442 }
443 });
444
Yoonseon Hanaa256052017-05-08 16:25:38 -0700445 deviceIdVirtualDeviceMap.remove(new VirtualDeviceId(networkId, deviceId));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500446 }
Brian Stanke7a81b532016-06-14 15:43:51 -0400447 }
448
449 @Override
450 public VirtualHost addHost(NetworkId networkId, HostId hostId, MacAddress mac,
451 VlanId vlan, HostLocation location, Set<IpAddress> ips) {
452 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800453 checkState(virtualPortExists(networkId, location.deviceId(), location.port()),
454 "The virtual port has not been created.");
Brian Stanke7a81b532016-06-14 15:43:51 -0400455 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
456 if (hostIdSet == null) {
457 hostIdSet = new HashSet<>();
458 }
459 VirtualHost virtualhost = new DefaultVirtualHost(networkId, hostId, mac, vlan, location, ips);
460 //TODO update both maps in one transaction.
461 hostIdVirtualHostMap.put(hostId, virtualhost);
462 hostIdSet.add(hostId);
463 networkIdHostIdSetMap.put(networkId, hostIdSet);
464 return virtualhost;
465 }
466
467 @Override
468 public void removeHost(NetworkId networkId, HostId hostId) {
469 checkState(networkExists(networkId), "The network has not been added.");
470 //TODO update both maps in one transaction.
471
472 Set<HostId> hostIdSet = new HashSet<>();
473 networkIdHostIdSetMap.get(networkId).forEach(hostId1 -> {
474 if (hostId1.equals(hostId)) {
475 hostIdSet.add(hostId1);
476 }
477 });
478
479 if (hostIdSet != null) {
480 networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
481 if (existingHostIds == null || existingHostIds.isEmpty()) {
482 return new HashSet<>();
483 } else {
484 return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
485 }
486 });
487
488 hostIdVirtualHostMap.remove(hostId);
489 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700490 }
491
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800492 /**
493 * Returns if the given virtual port exists.
494 *
495 * @param networkId network identifier
496 * @param deviceId virtual device Id
497 * @param portNumber virtual port number
498 * @return true if the virtual port exists, false otherwise.
499 */
500 private boolean virtualPortExists(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
501 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
502 if (virtualPortSet != null) {
503 return virtualPortSet.stream().anyMatch(
504 p -> p.element().id().equals(deviceId) &&
505 p.number().equals(portNumber));
506 } else {
507 return false;
508 }
509 }
510
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700511 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400512 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
513 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500514 checkState(networkExists(networkId), "The network has not been added.");
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800515 checkState(virtualPortExists(networkId, src.deviceId(), src.port()),
516 "The source virtual port has not been added.");
517 checkState(virtualPortExists(networkId, dst.deviceId(), dst.port()),
518 "The destination virtual port has not been added.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500519 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
520 if (virtualLinkSet == null) {
521 virtualLinkSet = new HashSet<>();
522 }
Harold Huang7362e672017-04-19 10:00:11 +0800523
Brian Stanke9a108972016-04-11 15:25:17 -0400524 // validate that the link does not already exist in this network
Harold Huang7362e672017-04-19 10:00:11 +0800525 checkState(getLink(networkId, src, dst) == null,
526 "The virtual link already exists");
527 checkState(getLink(networkId, src, null) == null,
528 "The source connection point has been used by another link");
529 checkState(getLink(networkId, null, dst) == null,
530 "The destination connection point has been used by another link");
Brian Stanke9a108972016-04-11 15:25:17 -0400531
532 VirtualLink virtualLink = DefaultVirtualLink.builder()
533 .networkId(networkId)
534 .src(src)
535 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400536 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400537 .tunnelId(realizedBy)
538 .build();
539
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500540 virtualLinkSet.add(virtualLink);
541 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
542 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700543 }
544
545 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400546 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400547 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
548 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
549 if (virtualLinkSet == null) {
550 virtualLinkSet = new HashSet<>();
Harold Huang7362e672017-04-19 10:00:11 +0800551 networkIdVirtualLinkSetMap.put(virtualLink.networkId(), virtualLinkSet);
552 log.warn("The updated virtual link {} has not been added", virtualLink);
553 return;
Brian Stanke9a108972016-04-11 15:25:17 -0400554 }
Harold Huang7362e672017-04-19 10:00:11 +0800555 if (!virtualLinkSet.remove(virtualLink)) {
556 log.warn("The updated virtual link {} does not exist", virtualLink);
557 return;
558 }
Brian Stanke9a108972016-04-11 15:25:17 -0400559
560 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
561 .networkId(virtualLink.networkId())
562 .src(virtualLink.src())
563 .dst(virtualLink.dst())
564 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400565 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400566 .build();
567
568 virtualLinkSet.add(newVirtualLink);
569 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
570 }
571
572 @Override
573 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500574 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500575
Brian Stanke9a108972016-04-11 15:25:17 -0400576 final VirtualLink virtualLink = getLink(networkId, src, dst);
577 if (virtualLink == null) {
Harold Huang7362e672017-04-19 10:00:11 +0800578 log.warn("The removed virtual link between {} and {} does not exist", src, dst);
Brian Stanke9a108972016-04-11 15:25:17 -0400579 return null;
580 }
Brian Stanke5df14472016-03-11 19:34:38 -0500581 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400582 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500583
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500584 if (virtualLinkSet != null) {
585 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
586 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700587 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500588 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700589 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500590 }
591 });
592 }
Brian Stanke9a108972016-04-11 15:25:17 -0400593 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700594 }
595
596 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700597 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId,
598 PortNumber portNumber, ConnectPoint realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500599 checkState(networkExists(networkId), "The network has not been added.");
600 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700601
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500602 if (virtualPortSet == null) {
603 virtualPortSet = new HashSet<>();
604 }
Yoonseon Han6c603892016-09-01 11:52:21 -0700605
Yoonseon Hanaa256052017-05-08 16:25:38 -0700606 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500607 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
Yoonseon Han6c603892016-09-01 11:52:21 -0700608
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800609 checkState(!virtualPortExists(networkId, deviceId, portNumber),
610 "The requested Port Number has been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700611
612 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device,
613 portNumber, realizedBy);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500614 virtualPortSet.add(virtualPort);
615 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500616 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400617 networkId, device, virtualPort));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500618 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700619 }
620
621 @Override
Yoonseon Han6c603892016-09-01 11:52:21 -0700622 public void bindPort(NetworkId networkId, DeviceId deviceId,
623 PortNumber portNumber, ConnectPoint realizedBy) {
624
625 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap
626 .get(networkId);
627
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800628 Optional<VirtualPort> virtualPortOptional = virtualPortSet.stream().filter(
Yoonseon Han6c603892016-09-01 11:52:21 -0700629 p -> p.element().id().equals(deviceId) &&
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800630 p.number().equals(portNumber)).findFirst();
631 checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
Yoonseon Han6c603892016-09-01 11:52:21 -0700632
Yoonseon Hanaa256052017-05-08 16:25:38 -0700633 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Yoonseon Han6c603892016-09-01 11:52:21 -0700634 checkNotNull(device, "The device has not been created for deviceId: "
635 + deviceId);
636
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800637 VirtualPort vPort = virtualPortOptional.get();
Yoonseon Han6c603892016-09-01 11:52:21 -0700638 virtualPortSet.remove(vPort);
639 vPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
640 virtualPortSet.add(vPort);
641 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
Claudine Chiu7f872a72016-12-16 13:51:39 -0500642 notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400643 networkId, device, vPort));
Yoonseon Han6c603892016-09-01 11:52:21 -0700644 }
645
646 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700647 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500648 checkState(networkExists(networkId), "The network has not been added.");
Yoonseon Hanaa256052017-05-08 16:25:38 -0700649 VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
Claudine Chiu465a2602017-03-17 18:33:36 -0400650 checkNotNull(device, "The device has not been created for deviceId: "
651 + deviceId);
Brian Stanke5df14472016-03-11 19:34:38 -0500652
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800653 if (networkIdVirtualPortSetMap.get(networkId) == null) {
654 log.warn("No port has been created for NetworkId: {}", networkId);
655 return;
656 }
657
Brian Stanke5df14472016-03-11 19:34:38 -0500658 Set<VirtualPort> virtualPortSet = new HashSet<>();
659 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
660 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
661 virtualPortSet.add(port);
662 }
663 });
664
Claudine Chiu7f872a72016-12-16 13:51:39 -0500665 if (!virtualPortSet.isEmpty()) {
666 AtomicBoolean portRemoved = new AtomicBoolean(false);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500667 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
668 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700669 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500670 } else {
Claudine Chiu7f872a72016-12-16 13:51:39 -0500671 portRemoved.set(true);
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700672 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500673 }
674 });
Claudine Chiu7f872a72016-12-16 13:51:39 -0500675 if (portRemoved.get()) {
676 virtualPortSet.forEach(virtualPort -> notifyDelegate(
677 new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
Claudine Chiu465a2602017-03-17 18:33:36 -0400678 networkId, device, virtualPort)
Claudine Chiu7f872a72016-12-16 13:51:39 -0500679 ));
Harold Huangb7d6b8e2017-04-03 17:13:33 +0800680
681 //Remove all the virtual links connected to this virtual port
682 Set<VirtualLink> existingVirtualLinks = networkIdVirtualLinkSetMap.get(networkId);
683 if (existingVirtualLinks != null && !existingVirtualLinks.isEmpty()) {
684 Set<VirtualLink> virtualLinkSet = new HashSet<>();
685 ConnectPoint cp = new ConnectPoint(deviceId, portNumber);
686 existingVirtualLinks.forEach(virtualLink -> {
687 if (virtualLink.src().equals(cp) || virtualLink.dst().equals(cp)) {
688 virtualLinkSet.add(virtualLink);
689 }
690 });
691 virtualLinkSet.forEach(virtualLink ->
692 removeLink(networkId, virtualLink.src(), virtualLink.dst()));
693 }
694
695 //Remove all the hosts connected to this virtual port
696 Set<HostId> hostIdSet = new HashSet<>();
697 hostIdVirtualHostMap.forEach((hostId, virtualHost) -> {
698 if (virtualHost.location().deviceId().equals(deviceId) &&
699 virtualHost.location().port().equals(portNumber)) {
700 hostIdSet.add(hostId);
701 }
702 });
703 hostIdSet.forEach(hostId -> removeHost(networkId, hostId));
Claudine Chiu7f872a72016-12-16 13:51:39 -0500704 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500705 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700706 }
707
708 @Override
709 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500710 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
711 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
712 if (networkIdSet != null) {
713 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
714 }
715 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700716 }
717
718 @Override
Brian Stanke86914282016-05-25 15:36:50 -0400719 public VirtualNetwork getNetwork(NetworkId networkId) {
720 return networkIdVirtualNetworkMap.get(networkId);
721 }
722
723 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700724 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500725 checkState(networkExists(networkId), "The network has not been added.");
726 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
727 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
728 if (deviceIdSet != null) {
Yoonseon Hanaa256052017-05-08 16:25:38 -0700729 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(
730 deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId))));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500731 }
732 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700733 }
734
735 @Override
Brian Stanke7a81b532016-06-14 15:43:51 -0400736 public Set<VirtualHost> getHosts(NetworkId networkId) {
737 checkState(networkExists(networkId), "The network has not been added.");
738 Set<HostId> hostIdSet = networkIdHostIdSetMap.get(networkId);
739 Set<VirtualHost> virtualHostSet = new HashSet<>();
740 if (hostIdSet != null) {
741 hostIdSet.forEach(hostId -> virtualHostSet.add(hostIdVirtualHostMap.get(hostId)));
742 }
743 return ImmutableSet.copyOf(virtualHostSet);
744 }
745
746 @Override
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700747 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500748 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500749 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
750 if (virtualLinkSet == null) {
751 virtualLinkSet = new HashSet<>();
752 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500753 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700754 }
755
Brian Stanke612cebf2016-05-02 10:21:33 -0400756 @Override
757 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400758 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
759 if (virtualLinkSet == null) {
760 return null;
761 }
762
763 VirtualLink virtualLink = null;
764 for (VirtualLink link : virtualLinkSet) {
Harold Huang7362e672017-04-19 10:00:11 +0800765 if (src == null && link.dst().equals(dst)) {
766 virtualLink = link;
767 break;
768 } else if (dst == null && link.src().equals(src)) {
769 virtualLink = link;
770 break;
771 } else if (link.src().equals(src) && link.dst().equals(dst)) {
Brian Stanke9a108972016-04-11 15:25:17 -0400772 virtualLink = link;
773 break;
774 }
775 }
776 return virtualLink;
777 }
778
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700779 @Override
780 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500781 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500782 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
783 if (virtualPortSet == null) {
784 virtualPortSet = new HashSet<>();
785 }
786
Brian Stanke612cebf2016-05-02 10:21:33 -0400787 if (deviceId == null) {
788 return ImmutableSet.copyOf(virtualPortSet);
789 }
790
Brian Stanke5df14472016-03-11 19:34:38 -0500791 Set<VirtualPort> portSet = new HashSet<>();
792 virtualPortSet.forEach(virtualPort -> {
793 if (virtualPort.element().id().equals(deviceId)) {
794 portSet.add(virtualPort);
795 }
796 });
797 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500798 }
799
Brian Stanke11f6d532016-07-05 16:17:59 -0400800 @Override
801 public synchronized void addOrUpdateIntent(Intent intent, IntentState state) {
802 checkNotNull(intent, "Intent cannot be null");
803 IntentData intentData = removeIntent(intent.key());
804 if (intentData == null) {
805 intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis()));
806 } else {
807 intentData = new IntentData(intent, state, intentData.version());
808 }
809 intentKeyIntentDataMap.put(intent.key(), intentData);
810 }
811
812 @Override
813 public IntentData removeIntent(Key intentKey) {
814 checkNotNull(intentKey, "Intent key cannot be null");
815 return intentKeyIntentDataMap.remove(intentKey);
816 }
817
818 @Override
819 public void addTunnelId(Intent intent, TunnelId tunnelId) {
820 // Add the tunnelId to the intent key set map
821 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key());
822 if (tunnelIdSet == null) {
823 tunnelIdSet = new HashSet<>();
824 }
825 tunnelIdSet.add(tunnelId);
826 intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet);
827 }
828
829 @Override
830 public Set<TunnelId> getTunnelIds(Intent intent) {
831 Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key());
832 return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet);
833 }
834
835 @Override
836 public void removeTunnelId(Intent intent, TunnelId tunnelId) {
837 Set<TunnelId> tunnelIdSet = new HashSet<>();
838 intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> {
839 if (tunnelId1.equals(tunnelId)) {
840 tunnelIdSet.add(tunnelId);
841 }
842 });
843
844 if (!tunnelIdSet.isEmpty()) {
845 intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> {
846 if (existingTunnelIds == null || existingTunnelIds.isEmpty()) {
847 return new HashSet<>();
848 } else {
849 return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet));
850 }
851 });
852 }
853 }
854
855 @Override
856 public Set<Intent> getIntents() {
857 Set<Intent> intents = new HashSet<>();
858 intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent()));
859 return ImmutableSet.copyOf(intents);
860 }
861
862 @Override
863 public Intent getIntent(Key key) {
864 IntentData intentData = intentKeyIntentDataMap.get(key);
865 return intentData == null ? null : intentData.intent();
866 }
867
868 @Override
869 public Set<IntentData> getIntentData() {
870 return ImmutableSet.copyOf(intentKeyIntentDataMap.values());
871 }
872
873 @Override
874 public IntentData getIntentData(Key key) {
875 IntentData intentData = intentKeyIntentDataMap.get(key);
876 return intentData == null ? null : new IntentData(intentData);
877 }
878
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500879 /**
880 * Listener class to map listener set events to the virtual network events.
881 */
882 private class InternalSetListener implements SetEventListener<TenantId> {
883 @Override
884 public void event(SetEvent<TenantId> event) {
885 VirtualNetworkEvent.Type type = null;
886 switch (event.type()) {
887 case ADD:
888 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
889 break;
890 case REMOVE:
891 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
892 break;
893 default:
894 log.error("Unsupported event type: " + event.type());
895 }
896 notifyDelegate(new VirtualNetworkEvent(type, null));
897 }
898 }
899
900 /**
901 * Listener class to map listener map events to the virtual network events.
902 */
Claudine Chiu945828d2016-11-21 12:47:07 -0500903 private class InternalMapListener<K, V> implements MapEventListener<K, V> {
904
905 private final BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent;
906
907 InternalMapListener(BiFunction<MapEvent.Type, V, VirtualNetworkEvent> createEvent) {
908 this.createEvent = createEvent;
909 }
910
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500911 @Override
Claudine Chiu945828d2016-11-21 12:47:07 -0500912 public void event(MapEvent<K, V> event) {
913 checkNotNull(event.key());
914 VirtualNetworkEvent vnetEvent = null;
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500915 switch (event.type()) {
916 case INSERT:
Claudine Chiu945828d2016-11-21 12:47:07 -0500917 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500918 break;
919 case UPDATE:
920 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
Claudine Chiu945828d2016-11-21 12:47:07 -0500921 vnetEvent = createEvent.apply(MapEvent.Type.REMOVE, event.oldValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500922 } else {
Claudine Chiu945828d2016-11-21 12:47:07 -0500923 vnetEvent = createEvent.apply(event.type(), event.newValue().value());
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500924 }
925 break;
926 case REMOVE:
Claudine Chiu945828d2016-11-21 12:47:07 -0500927 if (event.oldValue() != null) {
928 vnetEvent = createEvent.apply(event.type(), event.oldValue().value());
929 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500930 break;
931 default:
932 log.error("Unsupported event type: " + event.type());
933 }
Claudine Chiu945828d2016-11-21 12:47:07 -0500934 if (vnetEvent != null) {
935 notifyDelegate(vnetEvent);
936 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500937 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700938 }
Yoonseon Hanaa256052017-05-08 16:25:38 -0700939
940 /**
941 * A wrapper class to isolate device id from other virtual networks.
942 */
943
944 private static class VirtualDeviceId {
945
946 NetworkId networkId;
947 DeviceId deviceId;
948
949 public VirtualDeviceId(NetworkId networkId, DeviceId deviceId) {
950 this.networkId = networkId;
951 this.deviceId = deviceId;
952 }
953
954 public NetworkId getNetworkId() {
955 return networkId;
956 }
957
958 public DeviceId getDeviceId() {
959 return deviceId;
960 }
961
962 @Override
963 public int hashCode() {
964 return Objects.hash(networkId, deviceId);
965 }
966
967 @Override
968 public boolean equals(Object obj) {
969 if (this == obj) {
970 return true;
971 }
972
973 if (obj instanceof VirtualDeviceId) {
974 VirtualDeviceId that = (VirtualDeviceId) obj;
975 return this.deviceId.equals(that.deviceId) &&
976 this.networkId.equals(that.networkId);
977 }
978 return false;
979 }
980 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700981}