blob: a3ada37af8cc85e12d5f4bb0df0fca6de798612b [file] [log] [blame]
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +02001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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 */
16
17package org.onosproject.sdxl2;
18
19import com.google.common.collect.ImmutableSet;
pierventre3849e562016-05-11 11:47:32 +020020import com.google.common.collect.Sets;
Carolina Fernandezad893432016-07-18 11:11:34 +020021import org.apache.felix.scr.annotations.Activate;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020022import org.apache.felix.scr.annotations.Component;
Carolina Fernandezad893432016-07-18 11:11:34 +020023import org.apache.felix.scr.annotations.Deactivate;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
pierventre3849e562016-05-11 11:47:32 +020027import org.onlab.packet.VlanId;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020028import org.onlab.util.KryoNamespace;
29import org.onosproject.store.primitives.DefaultDistributedSet;
30import org.onosproject.store.serializers.KryoNamespaces;
pierventre3849e562016-05-11 11:47:32 +020031import org.onosproject.store.service.ConsistentMap;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020032import org.onosproject.store.service.DistributedPrimitive;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020033import org.onosproject.store.service.Serializer;
34import org.onosproject.store.service.StorageService;
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
Carolina Fernandezad893432016-07-18 11:11:34 +020038import java.util.Iterator;
pierventre3849e562016-05-11 11:47:32 +020039import java.util.List;
40import java.util.Map;
41import java.util.Optional;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020042import java.util.Set;
pierventre3849e562016-05-11 11:47:32 +020043import java.util.concurrent.ConcurrentHashMap;
44import java.util.stream.Collectors;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020045
Carolina Fernandezad893432016-07-18 11:11:34 +020046import static java.lang.String.format;
pierventre1483e642016-06-08 18:52:29 +020047
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020048/**
pierventre3849e562016-05-11 11:47:32 +020049 * SDX-L2 Store implementation backed by different distributed primitives.
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020050 */
51@Component(immediate = true)
52@Service
53public class SdxL2DistributedStore implements SdxL2Store {
54
55 private static Logger log = LoggerFactory.getLogger(SdxL2DistributedStore.class);
56
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 private StorageService storageService;
59
pierventre3849e562016-05-11 11:47:32 +020060 private Set<String> sdxL2s;
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +020061
pierventre3849e562016-05-11 11:47:32 +020062 private Map<SdxL2ConnectionPoint, String> sdxL2CPs;
63 private ConsistentMap<SdxL2ConnectionPoint, String> sdxL2cps;
64
Carolina Fernandezad893432016-07-18 11:11:34 +020065 private Map<String, String> sdxL2VCs;
66 private ConsistentMap<String, String> sdxL2vcs;
67
pierventre3849e562016-05-11 11:47:32 +020068 private static String errorAddSdx = "It is not possible to add %s " +
69 "because it exists";
70
71 private static String errorRemoveSdx = "It is not possible to remove %s " +
72 "because it does not exist";
73
Carolina Fernandezad893432016-07-18 11:11:34 +020074 /*
75 Error definitions for CPs.
76 */
pierventre3849e562016-05-11 11:47:32 +020077 private static String errorAddSdxL2CPName = "It is not possible to add %s " +
78 "because there is a sdxl2cp with the same name";
79 private static String errorAddSdxL2CPVlans = "It is not possible to add %s " +
80 "because there is a conflict with %s on the vlan ids";
81 private static String errorAddSdxL2CPCP = "It is not possible to add %s " +
82 "because there is a conflict with %s on the connection point";
83 private static String errorAddSdxL2CPSdx = "It is not possible to add %s " +
Carolina Fernandezad893432016-07-18 11:11:34 +020084 "because the relative sdxl2 %s does not exist";
pierventre3849e562016-05-11 11:47:32 +020085
Carolina Fernandezad893432016-07-18 11:11:34 +020086 private static String errorGetSdxL2CP = "It is not possible to retrieve %s " +
87 "because it does not exist";
pierventre1483e642016-06-08 18:52:29 +020088 private static String errorGetSdxL2CPs = "It is not possible to list the sdxl2cps " +
pierventre3849e562016-05-11 11:47:32 +020089 "because sdxl2 %s does not exist";
90
91 private static String errorRemoveSdxL2CP = "It is not possible to remove %s " +
92 "because it does not exist";
93
Carolina Fernandezad893432016-07-18 11:11:34 +020094 /*
95 Error definitions for VCs.
96 */
97 private static String errorVCKey = "It is not possible to add vc because " +
98 "there is a problem with key %s (wrong format)";
99 private static String errorAddVCOverlap = "It is not possible to add vc " +
100 "because there is an overlap with %s";
101 private static String errorRemoveVC = "It is not possible to remove the " +
102 "vc because it does not exist";
103 private static String errorRemoveVCAux = "Virtual Circuit between %s and %s " +
104 "does not exist";
pierventre1483e642016-06-08 18:52:29 +0200105
Carolina Fernandezad893432016-07-18 11:11:34 +0200106 /**
107 * Activates the implementation of the SDX-L2 store.
108 */
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200109 @Activate
110 public void activate() {
111
112 KryoNamespace custom = KryoNamespace.newBuilder()
113 .register(KryoNamespaces.API)
114 .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
115 .register(new SdxL2ConnectionPointSerializer(), new Class[]{SdxL2ConnectionPoint.class})
116 .build();
117
118 sdxL2s = new DefaultDistributedSet<>(this.storageService
Carolina Fernandezad893432016-07-18 11:11:34 +0200119 .<String>setBuilder()
120 .withSerializer(Serializer.using(custom))
121 .withName("sdxl2s")
122 .build(), DistributedPrimitive.DEFAULT_OPERTATION_TIMEOUT_MILLIS);
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200123
pierventre3849e562016-05-11 11:47:32 +0200124 sdxL2cps = this.storageService
125 .<SdxL2ConnectionPoint, String>consistentMapBuilder()
126 .withSerializer(Serializer.using(custom))
127 .withName("sdxl2cps")
128 .build();
129 sdxL2CPs = sdxL2cps.asJavaMap();
130
Carolina Fernandezad893432016-07-18 11:11:34 +0200131 sdxL2vcs = this.storageService.<String, String>consistentMapBuilder()
132 .withSerializer(Serializer.using(custom))
133 .withName("vcs")
134 .build();
135 sdxL2VCs = sdxL2vcs.asJavaMap();
136
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200137 log.info("Started");
138 }
139
Carolina Fernandezad893432016-07-18 11:11:34 +0200140 /**
141 * Helper class called to initialise tests.
142 */
143 public void initForTest() {
144 this.sdxL2s = Sets.newHashSet();
145 this.sdxL2CPs = new ConcurrentHashMap<SdxL2ConnectionPoint, String>();
146 this.sdxL2VCs = new ConcurrentHashMap<String, String>();
147 }
148
149 /**
150 * Deactivates the implementation of the SDX-L2 store.
151 */
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200152 @Deactivate
153 public void deactivate() {
154 log.info("Stopped");
155 }
156
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200157 @Override
158 public void putSdxL2(String sdxl2) throws SdxL2Exception {
159 boolean inserted = sdxL2s.add(sdxl2);
160 if (!inserted) {
pierventre3849e562016-05-11 11:47:32 +0200161 throw new SdxL2Exception(String.format(errorAddSdx, sdxl2));
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200162 }
163 }
164
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200165 @Override
166 public void removeSdxL2(String sdxl2) throws SdxL2Exception {
167 boolean removed = sdxL2s.remove(sdxl2);
168 if (!removed) {
pierventre3849e562016-05-11 11:47:32 +0200169 throw new SdxL2Exception(String.format(errorRemoveSdx, sdxl2));
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200170 }
pierventre3849e562016-05-11 11:47:32 +0200171
172 Set<Map.Entry<SdxL2ConnectionPoint, String>> toRemove = sdxL2CPs.entrySet().parallelStream().filter(
173 key_value -> {
174 String sdxl2Temp = key_value.getValue();
175 return sdxl2Temp.equals(sdxl2) ? true : false;
176 }).collect(Collectors.toSet());
177 toRemove.forEach(key_value -> sdxL2CPs.remove(key_value.getKey()));
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200178 }
179
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200180 @Override
181 public Set<String> getSdxL2s() {
182 return ImmutableSet.copyOf(sdxL2s);
183 }
184
pierventre3849e562016-05-11 11:47:32 +0200185 @Override
186 public void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint connectionPoint) throws SdxL2Exception {
pierventre3849e562016-05-11 11:47:32 +0200187 boolean exist = sdxL2s.contains(sdxl2);
Carolina Fernandezad893432016-07-18 11:11:34 +0200188 String errorMissingSdxL2 = String.format(errorAddSdxL2CPSdx, connectionPoint.name(), sdxl2);
pierventre3849e562016-05-11 11:47:32 +0200189 if (!exist) {
Carolina Fernandezad893432016-07-18 11:11:34 +0200190 throw new SdxL2Exception(errorMissingSdxL2);
pierventre3849e562016-05-11 11:47:32 +0200191 }
192
193 Set<SdxL2ConnectionPoint> sdxl2cpsTemp = ImmutableSet.copyOf(sdxL2CPs.keySet());
194 Set<SdxL2ConnectionPoint> sdxl2cpsTempByName = sdxl2cpsTemp.parallelStream().filter(
Carolina Fernandezad893432016-07-18 11:11:34 +0200195 sdxl2cpTemp -> sdxl2cpTemp.name().equals(connectionPoint.name()
pierventre3849e562016-05-11 11:47:32 +0200196 )
197 ).collect(Collectors.toSet());
198
199 if (sdxl2cpsTempByName.size() != 0) {
200 throw new SdxL2Exception(String.format(errorAddSdxL2CPName, connectionPoint.name()));
201 }
202
pierventre3849e562016-05-11 11:47:32 +0200203 Set<SdxL2ConnectionPoint> sdxl2cpsByCP = sdxl2cpsTemp.parallelStream().filter(
Carolina Fernandezad893432016-07-18 11:11:34 +0200204 sdxl2cpTemp -> sdxl2cpTemp.connectPoint().equals(connectionPoint.connectPoint()
pierventre3849e562016-05-11 11:47:32 +0200205 )
206 ).collect(Collectors.toSet());
207
208 String tempName;
209 List<VlanId> vlans = connectionPoint.vlanIds();
210 for (VlanId vlanId : vlans) {
211 Set<SdxL2ConnectionPoint> sdxl2cpsByVlan = sdxl2cpsByCP.parallelStream().filter(
212 sdxl2cp_by_vlan -> (
213 sdxl2cp_by_vlan.vlanIds().contains(vlanId) || sdxl2cp_by_vlan.vlanIds().size() == 0
214 )).collect(Collectors.toSet());
215
Carolina Fernandezad893432016-07-18 11:11:34 +0200216 tempName = sdxl2cpsByVlan.iterator().hasNext() ? sdxl2cpsByVlan.iterator().next().name() : null;
pierventre3849e562016-05-11 11:47:32 +0200217
218 if (sdxl2cpsByVlan.size() != 0) {
219 throw new SdxL2Exception(String.format(errorAddSdxL2CPVlans, connectionPoint.name(), tempName));
220 }
221
222 }
223
Carolina Fernandezad893432016-07-18 11:11:34 +0200224 tempName = sdxl2cpsByCP.iterator().hasNext() ? sdxl2cpsByCP.iterator().next().name() : null;
pierventre3849e562016-05-11 11:47:32 +0200225 if (sdxl2cpsByCP.size() != 0 && vlans.size() == 0) {
226 throw new SdxL2Exception(String.format(errorAddSdxL2CPCP, connectionPoint.name(), tempName));
227 }
228
229 sdxL2CPs.put(connectionPoint, sdxl2);
pierventre3849e562016-05-11 11:47:32 +0200230 }
231
pierventre3849e562016-05-11 11:47:32 +0200232 @Override
233 public Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2) throws SdxL2Exception {
234
235 if (sdxl2.isPresent()) {
236
237 Set<Map.Entry<SdxL2ConnectionPoint, String>> toGet = sdxL2CPs.entrySet().parallelStream().filter(
238 key_value -> {
239 String sdxl2Temp = key_value.getValue();
240 return sdxl2Temp.equals(sdxl2.get()) ? true : false;
241 }).collect(Collectors.toSet());
242
243 Iterator<String> itsdxL2s = sdxL2s.iterator();
244 boolean found = false;
245 while (itsdxL2s.hasNext()) {
246 if (sdxl2.get().equals(itsdxL2s.next())) {
247 found = true;
248 }
249 }
250
251 if (!found) {
252 throw new SdxL2Exception(String.format(errorGetSdxL2CPs, sdxl2.get()));
253 }
254
255 Set<String> cpsTemp = Sets.newHashSet();
256 for (Map.Entry<SdxL2ConnectionPoint, String> cp : toGet) {
257 cpsTemp.add(cp.getKey().name());
258 }
259
260 return cpsTemp;
261 }
262
263 return ImmutableSet.copyOf(sdxL2CPs.keySet()).parallelStream().map(
264 SdxL2ConnectionPoint::name).collect(Collectors.toSet());
265
266 }
267
pierventre3849e562016-05-11 11:47:32 +0200268 @Override
269 public void removeSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception {
270
271 Set<SdxL2ConnectionPoint> sdxl2cpsTemp = ImmutableSet.copyOf(sdxL2CPs.keySet());
272 Set<SdxL2ConnectionPoint> sdxl2cpsTempByName = sdxl2cpsTemp.parallelStream().filter(
273 sdxl2cpTemp -> sdxl2cpTemp.name().equals(sdxl2cp
274 )
275 ).collect(Collectors.toSet());
276
277 if (sdxl2cpsTempByName.size() == 0) {
278 throw new SdxL2Exception(String.format(errorRemoveSdxL2CP, sdxl2cp));
279 }
280
281 for (SdxL2ConnectionPoint sdxl2cpTemp : sdxl2cpsTempByName) {
282 sdxL2CPs.remove(sdxl2cpTemp);
283 }
284
285 }
286
pierventre1483e642016-06-08 18:52:29 +0200287 @Override
288 public SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception {
289 SdxL2ConnectionPoint sdxl2cpTemp = ImmutableSet.copyOf(sdxL2CPs.keySet()).parallelStream()
290 .filter(sdxl2cp_temp -> sdxl2cp_temp.name().equals(sdxl2cp)).findFirst().orElse(null);
291
292 if (sdxl2cpTemp == null) {
293 throw new SdxL2Exception(String.format(errorGetSdxL2CP, sdxl2cp));
294 }
295
296 return sdxl2cpTemp;
297 }
298
Carolina Fernandezad893432016-07-18 11:11:34 +0200299 @Override
300 public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
301 throws SdxL2Exception {
302 Set<String> vcs = ImmutableSet.copyOf(
303 sdxL2VCs.keySet().parallelStream().filter((vctemp->vctemp.contains(sdxl2cplhs.toString())
304 || vctemp.contains(sdxl2cprhs.toString()))).collect(Collectors.toSet()));
305 for (String vctemp : vcs) {
306 String[] splitted = vctemp.split("~");
307
308 if (splitted.length != 2) {
309 throw new SdxL2Exception(String.format(errorVCKey, "add", vctemp));
310 }
311
312 if (!(!sdxl2cplhs.toString().equals(splitted[0]) &&
313 !sdxl2cplhs.toString().equals(splitted[1]) &&
314 !sdxl2cprhs.toString().equals(splitted[0]) &&
315 !sdxl2cprhs.toString().equals(splitted[1]))) {
316 throw new SdxL2Exception(String.format(errorAddVCOverlap, vctemp));
317 }
318 }
319
320 String cps = sdxl2cplhs.toString().compareTo(sdxl2cprhs.toString()) < 0 ?
321 format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cplhs, sdxl2cprhs) :
322 format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cprhs, sdxl2cplhs);
323 String name = sdxl2cplhs.name().compareTo(sdxl2cprhs.name().toString()) < 0 ?
324 format(SdxL2VCManager.NAME_FORMAT, sdxl2, sdxl2cplhs.name(), sdxl2cprhs.name()) :
325 format(SdxL2VCManager.NAME_FORMAT, sdxl2, sdxl2cprhs.name(), sdxl2cplhs.name());
326 sdxL2VCs.put(cps, name);
327 }
328
329 @Override
330 public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
331 throws SdxL2Exception {
332
333 String cps = sdxl2cplhs.toString().compareTo(sdxl2cprhs.toString()) < 0 ?
334 format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cplhs, sdxl2cprhs) :
335 format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cprhs, sdxl2cplhs);
336 String name = sdxL2VCs.remove(cps);
337 if (name == null) {
338 throw new SdxL2Exception(String.format(errorRemoveVC));
339 }
340 }
341
342 @Override
343 public void removeVC(SdxL2ConnectionPoint cp) throws SdxL2Exception {
344
345 Set<String> vcs = ImmutableSet.copyOf(sdxL2VCs.keySet()
346 .parallelStream()
347 .filter((vctemp -> vctemp.contains(cp.toString())))
348 .collect(Collectors.toSet()));
349
350 for (String vctemp : vcs) {
351 String[] splitted = vctemp.split("~");
352 if (splitted.length != 2) {
353 throw new SdxL2Exception(String.format(errorVCKey, "delete", vctemp));
354 }
355 if (cp.toString().equals(splitted[0]) || cp.toString().equals(splitted[1])) {
356 sdxL2VCs.remove(vctemp);
357 }
358 }
359 }
360
361 @Override
362 public void removeVCs(String sdxl2) {
363
364 Set<Map.Entry<String, String>> vcsToRemove = sdxL2VCs.entrySet().parallelStream().filter(key_value -> {
365 String[] fields = key_value.getValue().split(":");
366 return fields.length == 2 && fields[0].equals(sdxl2) ? true : false;
367 }).collect(Collectors.toSet());
368
369 vcsToRemove.forEach(key_value -> sdxL2VCs.remove(key_value.getKey()));
370 }
371
372 @Override
373 public String getVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
374 throws SdxL2Exception {
375 String cps = sdxl2cplhs.toString().compareTo(sdxl2cprhs.toString()) < 0 ?
376 format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cplhs, sdxl2cprhs) :
377 format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cprhs, sdxl2cplhs);
378
379 String encodedvc = ImmutableSet.copyOf(sdxL2VCs.keySet()).parallelStream().filter(
380 encoded_cps -> encoded_cps.equals(cps)).findFirst().orElse(null);
381
382 if (encodedvc == null) {
383 throw new SdxL2Exception(String.format(errorRemoveVCAux,
384 sdxl2cplhs.name(), sdxl2cprhs.name()));
385 }
386 return encodedvc;
387 }
388
389 @Override
390 public Set<String> getVCs(Optional<String> sdxl2) {
391 if (sdxl2.isPresent()) {
392 Set<String> vcs = ImmutableSet.copyOf(sdxL2VCs.values())
393 .parallelStream()
394 .filter(vc -> {
395 String[] parts = vc.split(":");
396 return parts.length == 2 && parts[0].equals(sdxl2.get());
397 }).collect(Collectors.toSet());
398
399 return vcs;
400 }
401 return ImmutableSet.copyOf(sdxL2VCs.values());
402 }
Pier Luigi Ventre0a023f42016-04-30 11:03:15 +0200403}