blob: 1452dfc18a9c37dc3f315cd0a0964c419a5f4242 [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 Stanke5df14472016-03-11 19:34:38 -050045import org.onosproject.net.DefaultDevice;
46import org.onosproject.net.DefaultPort;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050047import org.onosproject.net.Device;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070048import org.onosproject.net.DeviceId;
49import org.onosproject.net.Port;
50import org.onosproject.net.PortNumber;
51import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050052import org.onosproject.store.serializers.KryoNamespaces;
53import org.onosproject.store.service.ConsistentMap;
54import org.onosproject.store.service.DistributedSet;
55import org.onosproject.store.service.MapEvent;
56import org.onosproject.store.service.MapEventListener;
57import org.onosproject.store.service.Serializer;
58import org.onosproject.store.service.SetEvent;
59import org.onosproject.store.service.SetEventListener;
60import org.onosproject.store.service.StorageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070061import org.slf4j.Logger;
62
Brian Stanke0e5c94e2016-03-08 11:20:04 -050063import java.util.HashSet;
64import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070065import java.util.Set;
66
Brian Stanke0e5c94e2016-03-08 11:20:04 -050067import static com.google.common.base.Preconditions.checkNotNull;
68import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070069import static org.slf4j.LoggerFactory.getLogger;
70
71/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050072 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070073 */
74@Component(immediate = true)
75@Service
76public class DistributedVirtualNetworkStore
77 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
78 implements VirtualNetworkStore {
79
80 private final Logger log = getLogger(getClass());
81
Brian Stanke0e5c94e2016-03-08 11:20:04 -050082 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070084
Brian Stanke0e5c94e2016-03-08 11:20:04 -050085 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070087
Brian Stanke0e5c94e2016-03-08 11:20:04 -050088 private IdGenerator idGenerator;
89
90 // Track tenants by ID
91 private DistributedSet<TenantId> tenantIdSet;
92
93 // Listener for tenant events
94 private final SetEventListener<TenantId> setListener = new InternalSetListener();
95
96 // Track virtual networks by network Id
97 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
98 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
99
100 // Listener for virtual network events
101 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
102
103 // Track virtual network IDs by tenant Id
104 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
105 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
106
107 // Track virtual devices by device Id
108 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
109 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
110
111 // Track device IDs by network Id
112 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
113 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
114
115 // Track virtual links by network Id
116 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
117 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
118
119 // Track virtual ports by network Id
120 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
121 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
122
123 private static final Serializer SERIALIZER = Serializer
124 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
125 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700126 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500127 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500128 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500129 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500130 .register(DefaultVirtualDevice.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500131 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500132 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500133 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500134 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500135 .register(Device.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500136 .register(DefaultDevice.class)
137 .register(DefaultPort.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400138 .register(TunnelId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500139 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID).build());
140
141 /**
142 * Distributed network store service activate method.
143 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700144 @Activate
145 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500146 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
147
148 tenantIdSet = storageService.<TenantId>setBuilder()
149 .withSerializer(SERIALIZER)
150 .withName("onos-tenantId")
151 .withRelaxedReadConsistency()
152 .build()
153 .asDistributedSet();
154 tenantIdSet.addListener(setListener);
155
156 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
157 .withSerializer(SERIALIZER)
158 .withName("onos-networkId-virtualnetwork")
159 .withRelaxedReadConsistency()
160 .build();
161 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
162 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
163
164 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
165 .withSerializer(SERIALIZER)
166 .withName("onos-tenantId-networkIds")
167 .withRelaxedReadConsistency()
168 .build();
169 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
170
171 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
172 .withSerializer(SERIALIZER)
173 .withName("onos-deviceId-virtualdevice")
174 .withRelaxedReadConsistency()
175 .build();
176 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
177
178 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
179 .withSerializer(SERIALIZER)
180 .withName("onos-networkId-deviceIds")
181 .withRelaxedReadConsistency()
182 .build();
183 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
184
185 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
186 .withSerializer(SERIALIZER)
187 .withName("onos-networkId-virtuallinks")
188 .withRelaxedReadConsistency()
189 .build();
190 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
191
192 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
193 .withSerializer(SERIALIZER)
194 .withName("onos-networkId-virtualportss")
195 .withRelaxedReadConsistency()
196 .build();
197 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
198
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700199 log.info("Started");
200 }
201
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500202 /**
203 * Distributed network store service deactivate method.
204 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700205 @Deactivate
206 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500207 tenantIdSet.removeListener(setListener);
208 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700209 log.info("Stopped");
210 }
211
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500212 /**
213 * This method is used for Junit tests to set the CoreService instance, which
214 * is required to set the IdGenerator instance.
215 *
216 * @param coreService core service instance
217 */
218 public void setCoreService(CoreService coreService) {
219 this.coreService = coreService;
220 }
221
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700222 @Override
223 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500224 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700225 }
226
227 @Override
228 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500229 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700230 }
231
232 @Override
233 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500234 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700235 }
236
237 @Override
238 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500239
240 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
241 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
242 //TODO update both maps in one transaction.
243 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500244
245 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
246 if (networkIdSet == null) {
247 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500248 }
Brian Stanke5df14472016-03-11 19:34:38 -0500249 networkIdSet.add(virtualNetwork.id());
250 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
251
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500252 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700253 }
254
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500255 /**
256 * Returns a new network identifier from a virtual network block of identifiers.
257 *
258 * @return NetworkId network identifier
259 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700260 private NetworkId genNetworkId() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500261 return NetworkId.networkId(idGenerator.getNewId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700262 }
263
264
265 @Override
266 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500267 // Make sure that the virtual network exists before attempting to remove it.
268 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500269 //TODO update both maps in one transaction.
270
271 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500272 if (virtualNetwork == null) {
273 return;
274 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500275 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500276
Brian Stanke5df14472016-03-11 19:34:38 -0500277 Set<NetworkId> networkIdSet = new HashSet<>();
278 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
279 if (networkId1.id().equals(networkId.id())) {
280 networkIdSet.add(networkId1);
281 }
282 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500283
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500284 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
285 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700286 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500287 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700288 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500289 }
290 });
291 }
292 }
293
294 /**
295 * Returns if the network identifier exists.
296 *
297 * @param networkId network identifier
298 * @return true if the network identifier exists, false otherwise.
299 */
300 private boolean networkExists(NetworkId networkId) {
301 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700302 }
303
304 @Override
305 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500306 checkState(networkExists(networkId), "The network has not been added.");
307 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
308 if (deviceIdSet == null) {
309 deviceIdSet = new HashSet<>();
310 }
311 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
312 //TODO update both maps in one transaction.
313 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
314 deviceIdSet.add(deviceId);
315 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
316 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700317 }
318
319 @Override
320 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500321 checkState(networkExists(networkId), "The network has not been added.");
322 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500323
324 Set<DeviceId> deviceIdSet = new HashSet<>();
325 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
326 if (deviceId1.equals(deviceId)) {
327 deviceIdSet.add(deviceId1);
328 }
329 });
330
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500331 if (deviceIdSet != null) {
332 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
333 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700334 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500335 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700336 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500337 }
338 });
339
Brian Stanke5df14472016-03-11 19:34:38 -0500340 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500341 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700342 }
343
344 @Override
345 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500346 checkState(networkExists(networkId), "The network has not been added.");
347 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
348 if (virtualLinkSet == null) {
349 virtualLinkSet = new HashSet<>();
350 }
Brian Stanke9a108972016-04-11 15:25:17 -0400351 // validate that the link does not already exist in this network
352 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
353
354 VirtualLink virtualLink = DefaultVirtualLink.builder()
355 .networkId(networkId)
356 .src(src)
357 .dst(dst)
358 .tunnelId(realizedBy)
359 .build();
360
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500361 virtualLinkSet.add(virtualLink);
362 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
363 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700364 }
365
366 @Override
Brian Stanke9a108972016-04-11 15:25:17 -0400367 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId) {
368 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
369 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
370 if (virtualLinkSet == null) {
371 virtualLinkSet = new HashSet<>();
372 }
373 virtualLinkSet.remove(virtualLink);
374
375 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
376 .networkId(virtualLink.networkId())
377 .src(virtualLink.src())
378 .dst(virtualLink.dst())
379 .tunnelId(tunnelId)
380 .build();
381
382 virtualLinkSet.add(newVirtualLink);
383 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
384 }
385
386 @Override
387 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500388 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500389
Brian Stanke9a108972016-04-11 15:25:17 -0400390 final VirtualLink virtualLink = getLink(networkId, src, dst);
391 if (virtualLink == null) {
392 return null;
393 }
Brian Stanke5df14472016-03-11 19:34:38 -0500394 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400395 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500396
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500397 if (virtualLinkSet != null) {
398 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
399 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700400 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500401 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700402 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500403 }
404 });
405 }
Brian Stanke9a108972016-04-11 15:25:17 -0400406 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700407 }
408
409 @Override
410 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500411 checkState(networkExists(networkId), "The network has not been added.");
412 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
413 if (virtualPortSet == null) {
414 virtualPortSet = new HashSet<>();
415 }
416 Device device = deviceIdVirtualDeviceMap.get(deviceId);
417 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
418 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
419 virtualPortSet.add(virtualPort);
420 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
421 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700422 }
423
424 @Override
425 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500426 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500427
428 Set<VirtualPort> virtualPortSet = new HashSet<>();
429 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
430 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
431 virtualPortSet.add(port);
432 }
433 });
434
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500435 if (virtualPortSet != null) {
436 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
437 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700438 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500439 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700440 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500441 }
442 });
443 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700444 }
445
446 @Override
447 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500448 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
449 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
450 if (networkIdSet != null) {
451 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
452 }
453 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700454 }
455
456 @Override
457 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500458 checkState(networkExists(networkId), "The network has not been added.");
459 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
460 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
461 if (deviceIdSet != null) {
462 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
463 }
464 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700465 }
466
467 @Override
468 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500469 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500470 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
471 if (virtualLinkSet == null) {
472 virtualLinkSet = new HashSet<>();
473 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500474 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700475 }
476
Brian Stanke9a108972016-04-11 15:25:17 -0400477 /**
478 * Returns the virtual link matching the network identifier, source connect point,
479 * and destination connect point.
480 *
481 * @param networkId network identifier
482 * @param src source connect point
483 * @param dst destination connect point
484 * @return virtual link
485 */
486 private VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
487 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
488 if (virtualLinkSet == null) {
489 return null;
490 }
491
492 VirtualLink virtualLink = null;
493 for (VirtualLink link : virtualLinkSet) {
494 if (link.src().equals(src) && link.dst().equals(dst)) {
495 virtualLink = link;
496 break;
497 }
498 }
499 return virtualLink;
500 }
501
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700502 @Override
503 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500504 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500505 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
506 if (virtualPortSet == null) {
507 virtualPortSet = new HashSet<>();
508 }
509
510 Set<VirtualPort> portSet = new HashSet<>();
511 virtualPortSet.forEach(virtualPort -> {
512 if (virtualPort.element().id().equals(deviceId)) {
513 portSet.add(virtualPort);
514 }
515 });
516 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500517 }
518
519 /**
520 * Listener class to map listener set events to the virtual network events.
521 */
522 private class InternalSetListener implements SetEventListener<TenantId> {
523 @Override
524 public void event(SetEvent<TenantId> event) {
525 VirtualNetworkEvent.Type type = null;
526 switch (event.type()) {
527 case ADD:
528 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
529 break;
530 case REMOVE:
531 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
532 break;
533 default:
534 log.error("Unsupported event type: " + event.type());
535 }
536 notifyDelegate(new VirtualNetworkEvent(type, null));
537 }
538 }
539
540 /**
541 * Listener class to map listener map events to the virtual network events.
542 */
543 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
544 @Override
545 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
546 NetworkId networkId = checkNotNull(event.key());
547 VirtualNetworkEvent.Type type = null;
548 switch (event.type()) {
549 case INSERT:
550 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
551 break;
552 case UPDATE:
553 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
554 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
555 } else {
556 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
557 }
558 break;
559 case REMOVE:
560 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
561 break;
562 default:
563 log.error("Unsupported event type: " + event.type());
564 }
565 notifyDelegate(new VirtualNetworkEvent(type, networkId));
566 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700567 }
568}