blob: 800ecfd7c131050adbaa0582c8de2ce952cad9af [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;
47import org.onosproject.net.Port;
48import org.onosproject.net.PortNumber;
49import org.onosproject.store.AbstractStore;
Brian Stanke0e5c94e2016-03-08 11:20:04 -050050import org.onosproject.store.serializers.KryoNamespaces;
51import org.onosproject.store.service.ConsistentMap;
52import org.onosproject.store.service.DistributedSet;
53import org.onosproject.store.service.MapEvent;
54import org.onosproject.store.service.MapEventListener;
55import org.onosproject.store.service.Serializer;
56import org.onosproject.store.service.SetEvent;
57import org.onosproject.store.service.SetEventListener;
58import org.onosproject.store.service.StorageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070059import org.slf4j.Logger;
60
Brian Stanke0e5c94e2016-03-08 11:20:04 -050061import java.util.HashSet;
62import java.util.Map;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070063import java.util.Set;
64
Brian Stanke0e5c94e2016-03-08 11:20:04 -050065import static com.google.common.base.Preconditions.checkNotNull;
66import static com.google.common.base.Preconditions.checkState;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070067import static org.slf4j.LoggerFactory.getLogger;
68
69/**
Brian Stanke0e5c94e2016-03-08 11:20:04 -050070 * Implementation of the virtual network store.
Thomas Vachuska33979fd2015-07-31 11:41:14 -070071 */
72@Component(immediate = true)
73@Service
74public class DistributedVirtualNetworkStore
75 extends AbstractStore<VirtualNetworkEvent, VirtualNetworkStoreDelegate>
76 implements VirtualNetworkStore {
77
78 private final Logger log = getLogger(getClass());
79
Brian Stanke0e5c94e2016-03-08 11:20:04 -050080 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 protected StorageService storageService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070082
Brian Stanke0e5c94e2016-03-08 11:20:04 -050083 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected CoreService coreService;
Thomas Vachuska33979fd2015-07-31 11:41:14 -070085
Brian Stanke0e5c94e2016-03-08 11:20:04 -050086 private IdGenerator idGenerator;
87
88 // Track tenants by ID
89 private DistributedSet<TenantId> tenantIdSet;
90
91 // Listener for tenant events
92 private final SetEventListener<TenantId> setListener = new InternalSetListener();
93
94 // Track virtual networks by network Id
95 private ConsistentMap<NetworkId, VirtualNetwork> networkIdVirtualNetworkConsistentMap;
96 private Map<NetworkId, VirtualNetwork> networkIdVirtualNetworkMap;
97
98 // Listener for virtual network events
99 private final MapEventListener<NetworkId, VirtualNetwork> virtualMapListener = new InternalMapListener();
100
101 // Track virtual network IDs by tenant Id
102 private ConsistentMap<TenantId, Set<NetworkId>> tenantIdNetworkIdSetConsistentMap;
103 private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
104
105 // Track virtual devices by device Id
106 private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
107 private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
108
109 // Track device IDs by network Id
110 private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
111 private Map<NetworkId, Set<DeviceId>> networkIdDeviceIdSetMap;
112
113 // Track virtual links by network Id
114 private ConsistentMap<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetConsistentMap;
115 private Map<NetworkId, Set<VirtualLink>> networkIdVirtualLinkSetMap;
116
117 // Track virtual ports by network Id
118 private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap;
119 private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap;
120
121 private static final Serializer SERIALIZER = Serializer
122 .using(new KryoNamespace.Builder().register(KryoNamespaces.API)
123 .register(TenantId.class)
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700124 .register(NetworkId.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500125 .register(VirtualNetwork.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500126 .register(DefaultVirtualNetwork.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500127 .register(VirtualDevice.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500128 .register(DefaultVirtualDevice.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500129 .register(VirtualLink.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500130 .register(DefaultVirtualLink.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500131 .register(VirtualPort.class)
Brian Stanke5df14472016-03-11 19:34:38 -0500132 .register(DefaultVirtualPort.class)
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500133 .register(Device.class)
Brian Stanke9a108972016-04-11 15:25:17 -0400134 .register(TunnelId.class)
HIGUCHI Yuta03666a32016-05-18 11:49:09 -0700135 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
136 .build("VirtualNetworkStore"));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500137
138 /**
139 * Distributed network store service activate method.
140 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700141 @Activate
142 public void activate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500143 idGenerator = coreService.getIdGenerator(VirtualNetworkService.VIRTUAL_NETWORK_TOPIC);
144
145 tenantIdSet = storageService.<TenantId>setBuilder()
146 .withSerializer(SERIALIZER)
147 .withName("onos-tenantId")
148 .withRelaxedReadConsistency()
149 .build()
150 .asDistributedSet();
151 tenantIdSet.addListener(setListener);
152
153 networkIdVirtualNetworkConsistentMap = storageService.<NetworkId, VirtualNetwork>consistentMapBuilder()
154 .withSerializer(SERIALIZER)
155 .withName("onos-networkId-virtualnetwork")
156 .withRelaxedReadConsistency()
157 .build();
158 networkIdVirtualNetworkConsistentMap.addListener(virtualMapListener);
159 networkIdVirtualNetworkMap = networkIdVirtualNetworkConsistentMap.asJavaMap();
160
161 tenantIdNetworkIdSetConsistentMap = storageService.<TenantId, Set<NetworkId>>consistentMapBuilder()
162 .withSerializer(SERIALIZER)
163 .withName("onos-tenantId-networkIds")
164 .withRelaxedReadConsistency()
165 .build();
166 tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
167
168 deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
169 .withSerializer(SERIALIZER)
170 .withName("onos-deviceId-virtualdevice")
171 .withRelaxedReadConsistency()
172 .build();
173 deviceIdVirtualDeviceMap = deviceIdVirtualDeviceConsistentMap.asJavaMap();
174
175 networkIdDeviceIdSetConsistentMap = storageService.<NetworkId, Set<DeviceId>>consistentMapBuilder()
176 .withSerializer(SERIALIZER)
177 .withName("onos-networkId-deviceIds")
178 .withRelaxedReadConsistency()
179 .build();
180 networkIdDeviceIdSetMap = networkIdDeviceIdSetConsistentMap.asJavaMap();
181
182 networkIdVirtualLinkSetConsistentMap = storageService.<NetworkId, Set<VirtualLink>>consistentMapBuilder()
183 .withSerializer(SERIALIZER)
184 .withName("onos-networkId-virtuallinks")
185 .withRelaxedReadConsistency()
186 .build();
187 networkIdVirtualLinkSetMap = networkIdVirtualLinkSetConsistentMap.asJavaMap();
188
189 networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder()
190 .withSerializer(SERIALIZER)
191 .withName("onos-networkId-virtualportss")
192 .withRelaxedReadConsistency()
193 .build();
194 networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap();
195
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700196 log.info("Started");
197 }
198
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500199 /**
200 * Distributed network store service deactivate method.
201 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700202 @Deactivate
203 public void deactivate() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500204 tenantIdSet.removeListener(setListener);
205 networkIdVirtualNetworkConsistentMap.removeListener(virtualMapListener);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700206 log.info("Stopped");
207 }
208
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500209 /**
210 * This method is used for Junit tests to set the CoreService instance, which
211 * is required to set the IdGenerator instance.
212 *
213 * @param coreService core service instance
214 */
215 public void setCoreService(CoreService coreService) {
216 this.coreService = coreService;
217 }
218
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700219 @Override
220 public void addTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500221 tenantIdSet.add(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700222 }
223
224 @Override
225 public void removeTenantId(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500226 tenantIdSet.remove(tenantId);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700227 }
228
229 @Override
230 public Set<TenantId> getTenantIds() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500231 return ImmutableSet.copyOf(tenantIdSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700232 }
233
234 @Override
235 public VirtualNetwork addNetwork(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500236
237 checkState(tenantIdSet.contains(tenantId), "The tenant has not been registered. " + tenantId.id());
238 VirtualNetwork virtualNetwork = new DefaultVirtualNetwork(genNetworkId(), tenantId);
239 //TODO update both maps in one transaction.
240 networkIdVirtualNetworkMap.put(virtualNetwork.id(), virtualNetwork);
Brian Stanke5df14472016-03-11 19:34:38 -0500241
242 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
243 if (networkIdSet == null) {
244 networkIdSet = new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500245 }
Brian Stanke5df14472016-03-11 19:34:38 -0500246 networkIdSet.add(virtualNetwork.id());
247 tenantIdNetworkIdSetMap.put(tenantId, networkIdSet);
248
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500249 return virtualNetwork;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700250 }
251
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500252 /**
253 * Returns a new network identifier from a virtual network block of identifiers.
254 *
255 * @return NetworkId network identifier
256 */
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700257 private NetworkId genNetworkId() {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500258 return NetworkId.networkId(idGenerator.getNewId());
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700259 }
260
261
262 @Override
263 public void removeNetwork(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500264 // Make sure that the virtual network exists before attempting to remove it.
265 if (networkExists(networkId)) {
Brian Stanke5df14472016-03-11 19:34:38 -0500266 //TODO update both maps in one transaction.
267
268 VirtualNetwork virtualNetwork = networkIdVirtualNetworkMap.remove(networkId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500269 if (virtualNetwork == null) {
270 return;
271 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500272 TenantId tenantId = virtualNetwork.tenantId();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500273
Brian Stanke5df14472016-03-11 19:34:38 -0500274 Set<NetworkId> networkIdSet = new HashSet<>();
275 tenantIdNetworkIdSetMap.get(tenantId).forEach(networkId1 -> {
276 if (networkId1.id().equals(networkId.id())) {
277 networkIdSet.add(networkId1);
278 }
279 });
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500280
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500281 tenantIdNetworkIdSetMap.compute(virtualNetwork.tenantId(), (id, existingNetworkIds) -> {
282 if (existingNetworkIds == null || existingNetworkIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700283 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500284 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700285 return new HashSet<>(Sets.difference(existingNetworkIds, networkIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500286 }
287 });
288 }
289 }
290
291 /**
292 * Returns if the network identifier exists.
293 *
294 * @param networkId network identifier
295 * @return true if the network identifier exists, false otherwise.
296 */
297 private boolean networkExists(NetworkId networkId) {
298 return (networkIdVirtualNetworkMap.containsKey(networkId));
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700299 }
300
301 @Override
302 public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500303 checkState(networkExists(networkId), "The network has not been added.");
304 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
305 if (deviceIdSet == null) {
306 deviceIdSet = new HashSet<>();
307 }
308 VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
309 //TODO update both maps in one transaction.
310 deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
311 deviceIdSet.add(deviceId);
312 networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
313 return virtualDevice;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700314 }
315
316 @Override
317 public void removeDevice(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500318 checkState(networkExists(networkId), "The network has not been added.");
319 //TODO update both maps in one transaction.
Brian Stanke5df14472016-03-11 19:34:38 -0500320
321 Set<DeviceId> deviceIdSet = new HashSet<>();
322 networkIdDeviceIdSetMap.get(networkId).forEach(deviceId1 -> {
323 if (deviceId1.equals(deviceId)) {
324 deviceIdSet.add(deviceId1);
325 }
326 });
327
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500328 if (deviceIdSet != null) {
329 networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
330 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700331 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500332 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700333 return new HashSet<>(Sets.difference(existingDeviceIds, deviceIdSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500334 }
335 });
336
Brian Stanke5df14472016-03-11 19:34:38 -0500337 deviceIdVirtualDeviceMap.remove(deviceId);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500338 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700339 }
340
341 @Override
342 public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500343 checkState(networkExists(networkId), "The network has not been added.");
344 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
345 if (virtualLinkSet == null) {
346 virtualLinkSet = new HashSet<>();
347 }
Brian Stanke9a108972016-04-11 15:25:17 -0400348 // validate that the link does not already exist in this network
349 checkState(getLink(networkId, src, dst) == null, "The virtual link already exists");
350
351 VirtualLink virtualLink = DefaultVirtualLink.builder()
352 .networkId(networkId)
353 .src(src)
354 .dst(dst)
355 .tunnelId(realizedBy)
356 .build();
357
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500358 virtualLinkSet.add(virtualLink);
359 networkIdVirtualLinkSetMap.put(networkId, virtualLinkSet);
360 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700361 }
362
363 @Override
Brian Stanke9a108972016-04-11 15:25:17 -0400364 public void updateLink(VirtualLink virtualLink, TunnelId tunnelId) {
365 checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
366 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
367 if (virtualLinkSet == null) {
368 virtualLinkSet = new HashSet<>();
369 }
370 virtualLinkSet.remove(virtualLink);
371
372 VirtualLink newVirtualLink = DefaultVirtualLink.builder()
373 .networkId(virtualLink.networkId())
374 .src(virtualLink.src())
375 .dst(virtualLink.dst())
376 .tunnelId(tunnelId)
377 .build();
378
379 virtualLinkSet.add(newVirtualLink);
380 networkIdVirtualLinkSetMap.put(newVirtualLink.networkId(), virtualLinkSet);
381 }
382
383 @Override
384 public VirtualLink removeLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500385 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500386
Brian Stanke9a108972016-04-11 15:25:17 -0400387 final VirtualLink virtualLink = getLink(networkId, src, dst);
388 if (virtualLink == null) {
389 return null;
390 }
Brian Stanke5df14472016-03-11 19:34:38 -0500391 Set<VirtualLink> virtualLinkSet = new HashSet<>();
Brian Stanke9a108972016-04-11 15:25:17 -0400392 virtualLinkSet.add(virtualLink);
Brian Stanke5df14472016-03-11 19:34:38 -0500393
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500394 if (virtualLinkSet != null) {
395 networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
396 if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700397 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500398 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700399 return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500400 }
401 });
402 }
Brian Stanke9a108972016-04-11 15:25:17 -0400403 return virtualLink;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700404 }
405
406 @Override
407 public VirtualPort addPort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber, Port realizedBy) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500408 checkState(networkExists(networkId), "The network has not been added.");
409 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
410 if (virtualPortSet == null) {
411 virtualPortSet = new HashSet<>();
412 }
413 Device device = deviceIdVirtualDeviceMap.get(deviceId);
414 checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
415 VirtualPort virtualPort = new DefaultVirtualPort(networkId, device, portNumber, realizedBy);
416 virtualPortSet.add(virtualPort);
417 networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
418 return virtualPort;
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700419 }
420
421 @Override
422 public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500423 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500424
425 Set<VirtualPort> virtualPortSet = new HashSet<>();
426 networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
427 if (port.element().id().equals(deviceId) && port.number().equals(portNumber)) {
428 virtualPortSet.add(port);
429 }
430 });
431
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500432 if (virtualPortSet != null) {
433 networkIdVirtualPortSetMap.compute(networkId, (id, existingVirtualPorts) -> {
434 if (existingVirtualPorts == null || existingVirtualPorts.isEmpty()) {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700435 return new HashSet<>();
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500436 } else {
HIGUCHI Yutac0f50452016-05-13 19:26:05 -0700437 return new HashSet<>(Sets.difference(existingVirtualPorts, virtualPortSet));
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500438 }
439 });
440 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700441 }
442
443 @Override
444 public Set<VirtualNetwork> getNetworks(TenantId tenantId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500445 Set<NetworkId> networkIdSet = tenantIdNetworkIdSetMap.get(tenantId);
446 Set<VirtualNetwork> virtualNetworkSet = new HashSet<>();
447 if (networkIdSet != null) {
448 networkIdSet.forEach(networkId -> virtualNetworkSet.add(networkIdVirtualNetworkMap.get(networkId)));
449 }
450 return ImmutableSet.copyOf(virtualNetworkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700451 }
452
453 @Override
454 public Set<VirtualDevice> getDevices(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500455 checkState(networkExists(networkId), "The network has not been added.");
456 Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
457 Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
458 if (deviceIdSet != null) {
459 deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
460 }
461 return ImmutableSet.copyOf(virtualDeviceSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700462 }
463
464 @Override
465 public Set<VirtualLink> getLinks(NetworkId networkId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500466 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500467 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
468 if (virtualLinkSet == null) {
469 virtualLinkSet = new HashSet<>();
470 }
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500471 return ImmutableSet.copyOf(virtualLinkSet);
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700472 }
473
Brian Stanke9a108972016-04-11 15:25:17 -0400474 /**
475 * Returns the virtual link matching the network identifier, source connect point,
476 * and destination connect point.
477 *
478 * @param networkId network identifier
479 * @param src source connect point
480 * @param dst destination connect point
481 * @return virtual link
482 */
483 private VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
484 Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
485 if (virtualLinkSet == null) {
486 return null;
487 }
488
489 VirtualLink virtualLink = null;
490 for (VirtualLink link : virtualLinkSet) {
491 if (link.src().equals(src) && link.dst().equals(dst)) {
492 virtualLink = link;
493 break;
494 }
495 }
496 return virtualLink;
497 }
498
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700499 @Override
500 public Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId) {
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500501 checkState(networkExists(networkId), "The network has not been added.");
Brian Stanke5df14472016-03-11 19:34:38 -0500502 Set<VirtualPort> virtualPortSet = networkIdVirtualPortSetMap.get(networkId);
503 if (virtualPortSet == null) {
504 virtualPortSet = new HashSet<>();
505 }
506
507 Set<VirtualPort> portSet = new HashSet<>();
508 virtualPortSet.forEach(virtualPort -> {
509 if (virtualPort.element().id().equals(deviceId)) {
510 portSet.add(virtualPort);
511 }
512 });
513 return ImmutableSet.copyOf(portSet);
Brian Stanke0e5c94e2016-03-08 11:20:04 -0500514 }
515
516 /**
517 * Listener class to map listener set events to the virtual network events.
518 */
519 private class InternalSetListener implements SetEventListener<TenantId> {
520 @Override
521 public void event(SetEvent<TenantId> event) {
522 VirtualNetworkEvent.Type type = null;
523 switch (event.type()) {
524 case ADD:
525 type = VirtualNetworkEvent.Type.TENANT_REGISTERED;
526 break;
527 case REMOVE:
528 type = VirtualNetworkEvent.Type.TENANT_UNREGISTERED;
529 break;
530 default:
531 log.error("Unsupported event type: " + event.type());
532 }
533 notifyDelegate(new VirtualNetworkEvent(type, null));
534 }
535 }
536
537 /**
538 * Listener class to map listener map events to the virtual network events.
539 */
540 private class InternalMapListener implements MapEventListener<NetworkId, VirtualNetwork> {
541 @Override
542 public void event(MapEvent<NetworkId, VirtualNetwork> event) {
543 NetworkId networkId = checkNotNull(event.key());
544 VirtualNetworkEvent.Type type = null;
545 switch (event.type()) {
546 case INSERT:
547 type = VirtualNetworkEvent.Type.NETWORK_ADDED;
548 break;
549 case UPDATE:
550 if ((event.oldValue().value() != null) && (event.newValue().value() == null)) {
551 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
552 } else {
553 type = VirtualNetworkEvent.Type.NETWORK_UPDATED;
554 }
555 break;
556 case REMOVE:
557 type = VirtualNetworkEvent.Type.NETWORK_REMOVED;
558 break;
559 default:
560 log.error("Unsupported event type: " + event.type());
561 }
562 notifyDelegate(new VirtualNetworkEvent(type, networkId));
563 }
Thomas Vachuska33979fd2015-07-31 11:41:14 -0700564 }
565}