blob: f12be558ed42976e6c2f1bdc79f90897dfb351bc [file] [log] [blame]
Sean Condon0e89bda2017-03-21 14:23:19 +00001/*
2 * Copyright 2017-present Open Networking Foundation
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 */
16package org.onosproject.incubator.net.l2monitoring.cfm.impl;
17
18import com.google.common.net.InternetDomainName;
19import org.apache.commons.lang3.tuple.ImmutablePair;
Sean Condon0e89bda2017-03-21 14:23:19 +000020import org.onlab.packet.MacAddress;
21import org.onlab.util.Identifier;
22import org.onlab.util.KryoNamespace;
23import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent;
24import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation;
25import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
26import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
27import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
28import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet;
29import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
30import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731;
31import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid;
32import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId;
33import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
34import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
35import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
36import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
37import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
38import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
39import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
Sean Condon96b896d2017-12-11 12:44:29 -080040import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
Sean Condon0e89bda2017-03-21 14:23:19 +000041import org.onosproject.incubator.net.l2monitoring.cfm.service.MdEvent;
42import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
43import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStoreDelegate;
Sean Condon0e89bda2017-03-21 14:23:19 +000044import org.onosproject.store.AbstractStore;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070045import org.onosproject.store.serializers.KryoNamespaces;
Sean Condon0e89bda2017-03-21 14:23:19 +000046import org.onosproject.store.service.ConsistentMap;
47import org.onosproject.store.service.MapEvent;
48import org.onosproject.store.service.MapEventListener;
49import org.onosproject.store.service.Serializer;
50import org.onosproject.store.service.StorageService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070051import org.osgi.service.component.annotations.Activate;
52import org.osgi.service.component.annotations.Component;
53import org.osgi.service.component.annotations.Deactivate;
54import org.osgi.service.component.annotations.Reference;
55import org.osgi.service.component.annotations.ReferenceCardinality;
Sean Condon0e89bda2017-03-21 14:23:19 +000056import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58
59import java.util.Collection;
60import java.util.Map;
61import java.util.Optional;
Sean Condon96b896d2017-12-11 12:44:29 -080062import java.util.Set;
63import java.util.stream.Collectors;
Sean Condon0e89bda2017-03-21 14:23:19 +000064
65/**
66 * Maintenance Domain Store implementation backed by consistent map.
67 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070068@Component(immediate = true, service = MdStore.class)
Sean Condon0e89bda2017-03-21 14:23:19 +000069public class DistributedMdStore extends AbstractStore<MdEvent, MdStoreDelegate>
70 implements MdStore {
71
72 private final Logger log = LoggerFactory.getLogger(getClass());
73
Ray Milkeyd84f89b2018-08-17 14:54:17 -070074 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sean Condon0e89bda2017-03-21 14:23:19 +000075 protected StorageService storageService;
76
77 private ConsistentMap<MdId, MaintenanceDomain> maintenanceDomainConsistentMap;
78 private Map<MdId, MaintenanceDomain> maintenanceDomainMap;
79
Sean Condon96b896d2017-12-11 12:44:29 -080080 private MapEventListener<MdId, MaintenanceDomain> mapListener = null;
Sean Condon0e89bda2017-03-21 14:23:19 +000081
82 @Activate
83 public void activate() {
84 maintenanceDomainConsistentMap = storageService
85 .<MdId, MaintenanceDomain>consistentMapBuilder()
86 .withName("onos-cfm-ma-map")
87 .withSerializer(Serializer.using(new KryoNamespace.Builder()
88 .register(KryoNamespaces.API)
89 .register(DefaultMaintenanceDomain.class)
90 .register(MdIdCharStr.class)
91 .register(MdIdDomainName.class)
92 .register(MdIdMacUint.class)
93 .register(MdIdNone.class)
94 .register(MaintenanceDomain.MdLevel.class)
95 .register(DefaultMaintenanceAssociation.class)
96 .register(MaIdCharStr.class)
97 .register(MaIdShort.class)
98 .register(MaId2Octet.class)
99 .register(MaIdIccY1731.class)
100 .register(MaIdPrimaryVid.class)
101 .register(MaIdRfc2685VpnId.class)
102 .register(MaintenanceAssociation.CcmInterval.class)
103 .register(DefaultComponent.class)
104 .register(MepId.class)
105 .register(Identifier.class)
106 .register(InternetDomainName.class)
107 .register(MacAddress.class)
108 .register(ImmutablePair.class)
Sean Condon3a1efef2018-02-24 13:16:03 +0000109 .register(org.onosproject.incubator.net.l2monitoring.cfm.Component.MhfCreationType.class)
110 .register(org.onosproject.incubator.net.l2monitoring.cfm.Component.IdPermissionType.class)
111 .register(org.onosproject.incubator.net.l2monitoring.cfm.Component.TagType.class)
Sean Condon0e89bda2017-03-21 14:23:19 +0000112 .build("md")))
113 .build();
Sean Condon96b896d2017-12-11 12:44:29 -0800114 mapListener = new InternalMdListener();
115 maintenanceDomainConsistentMap.addListener(mapListener);
Sean Condon0e89bda2017-03-21 14:23:19 +0000116
117 maintenanceDomainMap = maintenanceDomainConsistentMap.asJavaMap();
Sean Condon96b896d2017-12-11 12:44:29 -0800118 log.info("MDStore started");
119 }
120
121 @Deactivate
122 public void deactivate() {
123 maintenanceDomainConsistentMap.removeListener(mapListener);
124 log.info("Stopped");
Sean Condon0e89bda2017-03-21 14:23:19 +0000125 }
126
127 @Override
128 public Collection<MaintenanceDomain> getAllMaintenanceDomain() {
129 return maintenanceDomainMap.values();
130 }
131
132 @Override
133 public Optional<MaintenanceDomain> getMaintenanceDomain(MdId mdName) {
134 return Optional.ofNullable(
135 maintenanceDomainMap.get(mdName));
136 }
137
138 @Override
139 public boolean deleteMaintenanceDomain(MdId mdName) {
140 return maintenanceDomainMap.remove(mdName) == null ? false : true;
141 }
142
143 @Override
144 public boolean createUpdateMaintenanceDomain(MaintenanceDomain md) {
145 return maintenanceDomainMap.put(md.mdId(), md) == null ? false : true;
146 }
147
148 private class InternalMdListener implements MapEventListener<MdId, MaintenanceDomain> {
149 @Override
150 public void event(MapEvent<MdId, MaintenanceDomain> mapEvent) {
151 final MdEvent.Type type;
Sean Condon96b896d2017-12-11 12:44:29 -0800152 MaIdShort maId = null;
Sean Condon0e89bda2017-03-21 14:23:19 +0000153 switch (mapEvent.type()) {
154 case INSERT:
155 type = MdEvent.Type.MD_ADDED;
156 break;
157 case UPDATE:
Sean Condon96b896d2017-12-11 12:44:29 -0800158 // Examine the diff to see if it was a removal or addition of an MA caused it
159 if (mapEvent.oldValue().value().maintenanceAssociationList().size() >
160 mapEvent.newValue().value().maintenanceAssociationList().size()) {
161 Set<MaIdShort> newMaIds = mapEvent.newValue().value().maintenanceAssociationList()
162 .stream()
163 .map(MaintenanceAssociation::maId)
164 .collect(Collectors.toSet());
165 Optional<MaintenanceAssociation> removedMa =
166 mapEvent.oldValue().value().maintenanceAssociationList()
167 .stream()
168 .filter(maOld -> !newMaIds.contains(maOld.maId())).findFirst();
169 if (removedMa.isPresent()) {
170 maId = removedMa.get().maId();
171 }
172 type = MdEvent.Type.MA_REMOVED;
173 } else if (mapEvent.oldValue().value().maintenanceAssociationList().size() <
174 mapEvent.newValue().value().maintenanceAssociationList().size()) {
175 Set<MaIdShort> oldMaIds = mapEvent.oldValue().value().maintenanceAssociationList()
176 .stream()
177 .map(MaintenanceAssociation::maId)
178 .collect(Collectors.toSet());
179 Optional<MaintenanceAssociation> addedMa =
180 mapEvent.newValue().value().maintenanceAssociationList()
181 .stream()
182 .filter(maNew -> !oldMaIds.contains(maNew.maId())).findFirst();
183 if (addedMa.isPresent()) {
184 maId = addedMa.get().maId();
185 }
186 type = MdEvent.Type.MA_ADDED;
187 } else {
188 type = MdEvent.Type.MD_UPDATED;
189 }
Sean Condon0e89bda2017-03-21 14:23:19 +0000190 break;
191 case REMOVE:
192 default:
193 type = MdEvent.Type.MD_REMOVED;
194 break;
195 }
Sean Condon96b896d2017-12-11 12:44:29 -0800196 if (mapEvent.oldValue() != null && mapEvent.oldValue().value() != null) {
197 MaintenanceDomain oldMd = mapEvent.oldValue().value();
198 try {
199 if (maId != null) {
200 notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd, maId));
201 } else {
202 notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd));
203 }
204 } catch (CfmConfigException e) {
205 log.warn("Unable to copy MD {}", oldMd);
206 notifyDelegate(new MdEvent(type, mapEvent.key()));
207 }
208 } else {
209 notifyDelegate(new MdEvent(type, mapEvent.key()));
210 }
Sean Condon0e89bda2017-03-21 14:23:19 +0000211 }
212 }
213}