blob: 538109df5d1ae3e4938440c5123bcc2041d64b01 [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 Stanke0e5c94e2016-03-08 11:20:04 -050026import org.onlab.util.KryoNamespace;
27import org.onosproject.core.CoreService;
28import org.onosproject.core.IdGenerator;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070029import org.onosproject.incubator.net.tunnel.TunnelId;
30import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050031import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070032import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050033import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070034import org.onosproject.incubator.net.virtual.NetworkId;
35import org.onosproject.incubator.net.virtual.TenantId;
36import org.onosproject.incubator.net.virtual.VirtualDevice;
37import org.onosproject.incubator.net.virtual.VirtualLink;
38import org.onosproject.incubator.net.virtual.VirtualNetwork;
39import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050040import org.onosproject.incubator.net.virtual.VirtualNetworkService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070041import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
42import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
43import org.onosproject.incubator.net.virtual.VirtualPort;
44import org.onosproject.net.ConnectPoint;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050045import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070046import org.onosproject.net.DeviceId;
Brian Stanke612cebf2016-05-02 10:21:33 -040047import org.onosproject.net.Link;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070048import org.onosproject.net.Port;
49import org.onosproject.net.PortNumber;
50import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050051import org.onosproject.store.serializers.KryoNamespaces;
52import org.onosproject.store.service.ConsistentMap;
53import org.onosproject.store.service.DistributedSet;
54import org.onosproject.store.service.MapEvent;
55import org.onosproject.store.service.MapEventListener;
56import org.onosproject.store.service.Serializer;
57import org.onosproject.store.service.SetEvent;
58import org.onosproject.store.service.SetEventListener;
59import org.onosproject.store.service.StorageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070060import org.slf4j.Logger;
61
Brian Stanke0e5c94e2016-03-08 11:20:04 -050062import java.util.HashSet;
63import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070064import java.util.Set;
65
Brian Stanke0e5c94e2016-03-08 11:20:04 -050066import static com.google.common.base.Preconditions.checkNotNull;
67import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070068import static org.slf4j.LoggerFactory.getLogger;
69
70/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050071 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070072 */
73@Component(immediate = true)
74@Service
75public class DistributedVirtualNetworkStore
76 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
77 implements VirtualNetworkStore {
78
79 private final Logger log = getLogger(getClass());
80
Brian Stanke0e5c94e2016-03-08 11:20:04 -050081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070083
Brian Stanke0e5c94e2016-03-08 11:20:04 -050084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070086
Brian Stanke0e5c94e2016-03-08 11:20:04 -050087 private IdGenerator idGenerator;
88
89 // Track tenants by ID
90 private DistributedSet<TenantId> tenantIdSet;
91
92 // Listener for tenant events
93 private final SetEventListener<TenantId> setListener = new InternalSetListener();
94
95 // Track virtual networks by network Id
96 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
97 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
98
99 // Listener for virtual network events
100 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
101
102 // Track virtual network IDs by tenant Id
103 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
104 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
105
106 // Track virtual devices by device Id
107 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
108 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
109
110 // Track device IDs by network Id
111 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
112 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
113
114 // Track virtual links by network Id
115 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
116 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
117
118 // Track virtual ports by network Id
119 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
120 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
121
122 private static final Serializer SERIALIZER = Serializer
123 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
124 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700125 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500126 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500127 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500128 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500129 .register(DefaultVirtualDevice.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500130 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500131 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500132 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500133 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500134 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400135 .register(TunnelId.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700136 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
137 .build("VirtualNetworkStore"));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500138
139 /**
140 * Distributed network store service activate method.
141 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700142 @Activate
143 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500144 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
145
146 tenantIdSet = storageService.<TenantId>setBuilder()
147 .withSerializer(SERIALIZER)
148 .withName("onos-tenantId")
149 .withRelaxedReadConsistency()
150 .build()
151 .asDistributedSet();
152 tenantIdSet.addListener(setListener);
153
154 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
155 .withSerializer(SERIALIZER)
156 .withName("onos-networkId-virtualnetwork")
157 .withRelaxedReadConsistency()
158 .build();
159 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
160 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
161
162 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
163 .withSerializer(SERIALIZER)
164 .withName("onos-tenantId-networkIds")
165 .withRelaxedReadConsistency()
166 .build();
167 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
168
169 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
170 .withSerializer(SERIALIZER)
171 .withName("onos-deviceId-virtualdevice")
172 .withRelaxedReadConsistency()
173 .build();
174 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
175
176 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
177 .withSerializer(SERIALIZER)
178 .withName("onos-networkId-deviceIds")
179 .withRelaxedReadConsistency()
180 .build();
181 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
182
183 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
184 .withSerializer(SERIALIZER)
185 .withName("onos-networkId-virtuallinks")
186 .withRelaxedReadConsistency()
187 .build();
188 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
189
190 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
191 .withSerializer(SERIALIZER)
192 .withName("onos-networkId-virtualportss")
193 .withRelaxedReadConsistency()
194 .build();
195 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
196
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700197 log.info("Started");
198 }
199
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500200 /**
201 * Distributed network store service deactivate method.
202 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700203 @Deactivate
204 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500205 tenantIdSet.removeListener(setListener);
206 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700207 log.info("Stopped");
208 }
209
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500210 /**
211 * This method is used for Junit tests to set the CoreService instance, which
212 * is required to set the IdGenerator instance.
213 *
214 * @param coreService core service instance
215 */
216 public void setCoreService(CoreService coreService) {
217 this.coreService = coreService;
218 }
219
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700220 @Override
221 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500222 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700223 }
224
225 @Override
226 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500227 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700228 }
229
230 @Override
231 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500232 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700233 }
234
235 @Override
236 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500237
238 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
239 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
240 //TODO update both maps in one transaction.
241 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500242
243 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
244 if (networkIdSet == null) {
245 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500246 }
Brian Stanke5df14472016-03-11 19:34:38 -0500247 networkIdSet.add(virtualNetwork.id());
248 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
249
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500250 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700251 }
252
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500253 /**
254 * Returns a new network identifier from a virtual network block of identifiers.
255 *
256 * @return NetworkId network identifier
257 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700258 private NetworkId genNetworkId() {
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900259 NetworkId networkId;
260 do {
261 networkId = NetworkId.networkId(idGenerator.getNewId());
262 } while (!networkId.isVirtualNetworkId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700263
Kenji HIKICHIcfdf91b2016-05-25 13:04:45 +0900264 return networkId;
265 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700266
267 @Override
268 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500269 // Make sure that the virtual network exists before attempting to remove it.
270 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500271 //TODO update both maps in one transaction.
272
273 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500274 if (virtualNetwork == null) {
275 return;
276 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500277 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500278
Brian Stanke5df14472016-03-11 19:34:38 -0500279 Set<NetworkId> networkIdSet = new HashSet<>();
280 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
281 if (networkId1.id().equals(networkId.id())) {
282 networkIdSet.add(networkId1);
283 }
284 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500285
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500286 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
287 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700288 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500289 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700290 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500291 }
292 });
293 }
294 }
295
296 /**
297 * Returns if the network identifier exists.
298 *
299 * @param networkId network identifier
300 * @return true if the network identifier exists, false otherwise.
301 */
302 private boolean networkExists(NetworkId networkId) {
Brian Stanke612cebf2016-05-02 10:21:33 -0400303 checkNotNull(networkId, "The network identifier cannot be null.");
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500304 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700305 }
306
307 @Override
308 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500309 checkState(networkExists(networkId), "The network has not been added.");
310 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
311 if (deviceIdSet == null) {
312 deviceIdSet = new HashSet<>();
313 }
314 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
315 //TODO update both maps in one transaction.
316 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
317 deviceIdSet.add(deviceId);
318 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
319 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700320 }
321
322 @Override
323 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500324 checkState(networkExists(networkId), "The network has not been added.");
325 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500326
327 Set<DeviceId> deviceIdSet = new HashSet<>();
328 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
329 if (deviceId1.equals(deviceId)) {
330 deviceIdSet.add(deviceId1);
331 }
332 });
333
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500334 if (deviceIdSet != null) {
335 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
336 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700337 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500338 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700339 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500340 }
341 });
342
Brian Stanke5df14472016-03-11 19:34:38 -0500343 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500344 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700345 }
346
347 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400348 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
349 Link.State state, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500350 checkState(networkExists(networkId), "The network has not been added.");
351 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
352 if (virtualLinkSet == null) {
353 virtualLinkSet = new HashSet<>();
354 }
Brian Stanke9a108972016-04-11 15:25:17 -0400355 // validate that the link does not already exist in this network
356 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
357
358 VirtualLink virtualLink = DefaultVirtualLink.builder()
359 .networkId(networkId)
360 .src(src)
361 .dst(dst)
Brian Stanke612cebf2016-05-02 10:21:33 -0400362 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400363 .tunnelId(realizedBy)
364 .build();
365
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500366 virtualLinkSet.add(virtualLink);
367 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
368 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700369 }
370
371 @Override
Brian Stanke612cebf2016-05-02 10:21:33 -0400372 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
Brian Stanke9a108972016-04-11 15:25:17 -0400373 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
374 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
375 if (virtualLinkSet == null) {
376 virtualLinkSet = new HashSet<>();
377 }
378 virtualLinkSet.remove(virtualLink);
379
380 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
381 .networkId(virtualLink.networkId())
382 .src(virtualLink.src())
383 .dst(virtualLink.dst())
384 .tunnelId(tunnelId)
Brian Stanke612cebf2016-05-02 10:21:33 -0400385 .state(state)
Brian Stanke9a108972016-04-11 15:25:17 -0400386 .build();
387
388 virtualLinkSet.add(newVirtualLink);
389 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
390 }
391
392 @Override
393 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500394 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500395
Brian Stanke9a108972016-04-11 15:25:17 -0400396 final VirtualLink virtualLink = getLink(networkId, src, dst);
397 if (virtualLink == null) {
398 return null;
399 }
Brian Stanke5df14472016-03-11 19:34:38 -0500400 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400401 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500402
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500403 if (virtualLinkSet != null) {
404 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
405 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700406 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500407 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700408 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500409 }
410 });
411 }
Brian Stanke9a108972016-04-11 15:25:17 -0400412 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700413 }
414
415 @Override
416 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500417 checkState(networkExists(networkId), "The network has not been added.");
418 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
419 if (virtualPortSet == null) {
420 virtualPortSet = new HashSet<>();
421 }
422 Device device = deviceIdVirtualDeviceMap.get(deviceId);
423 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
424 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
425 virtualPortSet.add(virtualPort);
426 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
427 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700428 }
429
430 @Override
431 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500432 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500433
434 Set<VirtualPort> virtualPortSet = new HashSet<>();
435 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
436 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
437 virtualPortSet.add(port);
438 }
439 });
440
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500441 if (virtualPortSet != null) {
442 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
443 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700444 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500445 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700446 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500447 }
448 });
449 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700450 }
451
452 @Override
453 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500454 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
455 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
456 if (networkIdSet != null) {
457 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
458 }
459 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700460 }
461
462 @Override
463 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500464 checkState(networkExists(networkId), "The network has not been added.");
465 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
466 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
467 if (deviceIdSet != null) {
468 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
469 }
470 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700471 }
472
473 @Override
474 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500475 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500476 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
477 if (virtualLinkSet == null) {
478 virtualLinkSet = new HashSet<>();
479 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500480 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700481 }
482
Brian Stanke612cebf2016-05-02 10:21:33 -0400483 @Override
484 public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke9a108972016-04-11 15:25:17 -0400485 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
486 if (virtualLinkSet == null) {
487 return null;
488 }
489
490 VirtualLink virtualLink = null;
491 for (VirtualLink link : virtualLinkSet) {
492 if (link.src().equals(src) && link.dst().equals(dst)) {
493 virtualLink = link;
494 break;
495 }
496 }
497 return virtualLink;
498 }
499
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700500 @Override
501 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500502 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500503 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
504 if (virtualPortSet == null) {
505 virtualPortSet = new HashSet<>();
506 }
507
Brian Stanke612cebf2016-05-02 10:21:33 -0400508 if (deviceId == null) {
509 return ImmutableSet.copyOf(virtualPortSet);
510 }
511
Brian Stanke5df14472016-03-11 19:34:38 -0500512 Set<VirtualPort> portSet = new HashSet<>();
513 virtualPortSet.forEach(virtualPort -> {
514 if (virtualPort.element().id().equals(deviceId)) {
515 portSet.add(virtualPort);
516 }
517 });
518 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500519 }
520
521 /**
522 * Listener class to map listener set events to the virtual network events.
523 */
524 private class InternalSetListener implements SetEventListener<TenantId> {
525 @Override
526 public void event(SetEvent<TenantId> event) {
527 VirtualNetworkEvent.Type type = null;
528 switch (event.type()) {
529 case ADD:
530 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
531 break;
532 case REMOVE:
533 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
534 break;
535 default:
536 log.error("Unsupported event type: " + event.type());
537 }
538 notifyDelegate(new VirtualNetworkEvent(type, null));
539 }
540 }
541
542 /**
543 * Listener class to map listener map events to the virtual network events.
544 */
545 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
546 @Override
547 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
548 NetworkId networkId = checkNotNull(event.key());
549 VirtualNetworkEvent.Type type = null;
550 switch (event.type()) {
551 case INSERT:
552 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
553 break;
554 case UPDATE:
555 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
556 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
557 } else {
558 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
559 }
560 break;
561 case REMOVE:
562 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
563 break;
564 default:
565 log.error("Unsupported event type: " + event.type());
566 }
567 notifyDelegate(new VirtualNetworkEvent(type, networkId));
568 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700569 }
570}