blob: 81813f82ca35509a20ef3d4b364d97db8dc632f6 [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;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
Sean Condon96b896d2017-12-11 12:44:29 -080022import org.apache.felix.scr.annotations.Deactivate;
Sean Condon0e89bda2017-03-21 14:23:19 +000023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
26import org.onlab.packet.MacAddress;
27import org.onlab.util.Identifier;
28import org.onlab.util.KryoNamespace;
29import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent;
30import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation;
31import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
32import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation;
33import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain;
34import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet;
35import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr;
36import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731;
37import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid;
38import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId;
39import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
40import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
41import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr;
42import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName;
43import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint;
44import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone;
45import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
Sean Condon96b896d2017-12-11 12:44:29 -080046import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
Sean Condon0e89bda2017-03-21 14:23:19 +000047import org.onosproject.incubator.net.l2monitoring.cfm.service.MdEvent;
48import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
49import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStoreDelegate;
50import org.onosproject.store.serializers.KryoNamespaces;
51import org.onosproject.store.AbstractStore;
52import org.onosproject.store.service.ConsistentMap;
53import org.onosproject.store.service.MapEvent;
54import org.onosproject.store.service.MapEventListener;
55import org.onosproject.store.service.Serializer;
56import org.onosproject.store.service.StorageService;
57import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60import java.util.Collection;
61import java.util.Map;
62import java.util.Optional;
Sean Condon96b896d2017-12-11 12:44:29 -080063import java.util.Set;
64import java.util.stream.Collectors;
Sean Condon0e89bda2017-03-21 14:23:19 +000065
66/**
67 * Maintenance Domain Store implementation backed by consistent map.
68 */
69@Component(immediate = true)
70@Service
71public class DistributedMdStore extends AbstractStore<MdEvent, MdStoreDelegate>
72 implements MdStore {
73
74 private final Logger log = LoggerFactory.getLogger(getClass());
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected StorageService storageService;
78
79 private ConsistentMap<MdId, MaintenanceDomain> maintenanceDomainConsistentMap;
80 private Map<MdId, MaintenanceDomain> maintenanceDomainMap;
81
Sean Condon96b896d2017-12-11 12:44:29 -080082 private MapEventListener<MdId, MaintenanceDomain> mapListener = null;
Sean Condon0e89bda2017-03-21 14:23:19 +000083
84 @Activate
85 public void activate() {
86 maintenanceDomainConsistentMap = storageService
87 .<MdId, MaintenanceDomain>consistentMapBuilder()
88 .withName("onos-cfm-ma-map")
89 .withSerializer(Serializer.using(new KryoNamespace.Builder()
90 .register(KryoNamespaces.API)
91 .register(DefaultMaintenanceDomain.class)
92 .register(MdIdCharStr.class)
93 .register(MdIdDomainName.class)
94 .register(MdIdMacUint.class)
95 .register(MdIdNone.class)
96 .register(MaintenanceDomain.MdLevel.class)
97 .register(DefaultMaintenanceAssociation.class)
98 .register(MaIdCharStr.class)
99 .register(MaIdShort.class)
100 .register(MaId2Octet.class)
101 .register(MaIdIccY1731.class)
102 .register(MaIdPrimaryVid.class)
103 .register(MaIdRfc2685VpnId.class)
104 .register(MaintenanceAssociation.CcmInterval.class)
105 .register(DefaultComponent.class)
106 .register(MepId.class)
107 .register(Identifier.class)
108 .register(InternetDomainName.class)
109 .register(MacAddress.class)
110 .register(ImmutablePair.class)
Sean Condon3a1efef2018-02-24 13:16:03 +0000111 .register(org.onosproject.incubator.net.l2monitoring.cfm.Component.MhfCreationType.class)
112 .register(org.onosproject.incubator.net.l2monitoring.cfm.Component.IdPermissionType.class)
113 .register(org.onosproject.incubator.net.l2monitoring.cfm.Component.TagType.class)
Sean Condon0e89bda2017-03-21 14:23:19 +0000114 .build("md")))
115 .build();
Sean Condon96b896d2017-12-11 12:44:29 -0800116 mapListener = new InternalMdListener();
117 maintenanceDomainConsistentMap.addListener(mapListener);
Sean Condon0e89bda2017-03-21 14:23:19 +0000118
119 maintenanceDomainMap = maintenanceDomainConsistentMap.asJavaMap();
Sean Condon96b896d2017-12-11 12:44:29 -0800120 log.info("MDStore started");
121 }
122
123 @Deactivate
124 public void deactivate() {
125 maintenanceDomainConsistentMap.removeListener(mapListener);
126 log.info("Stopped");
Sean Condon0e89bda2017-03-21 14:23:19 +0000127 }
128
129 @Override
130 public Collection<MaintenanceDomain> getAllMaintenanceDomain() {
131 return maintenanceDomainMap.values();
132 }
133
134 @Override
135 public Optional<MaintenanceDomain> getMaintenanceDomain(MdId mdName) {
136 return Optional.ofNullable(
137 maintenanceDomainMap.get(mdName));
138 }
139
140 @Override
141 public boolean deleteMaintenanceDomain(MdId mdName) {
142 return maintenanceDomainMap.remove(mdName) == null ? false : true;
143 }
144
145 @Override
146 public boolean createUpdateMaintenanceDomain(MaintenanceDomain md) {
147 return maintenanceDomainMap.put(md.mdId(), md) == null ? false : true;
148 }
149
150 private class InternalMdListener implements MapEventListener<MdId, MaintenanceDomain> {
151 @Override
152 public void event(MapEvent<MdId, MaintenanceDomain> mapEvent) {
153 final MdEvent.Type type;
Sean Condon96b896d2017-12-11 12:44:29 -0800154 MaIdShort maId = null;
Sean Condon0e89bda2017-03-21 14:23:19 +0000155 switch (mapEvent.type()) {
156 case INSERT:
157 type = MdEvent.Type.MD_ADDED;
158 break;
159 case UPDATE:
Sean Condon96b896d2017-12-11 12:44:29 -0800160 // Examine the diff to see if it was a removal or addition of an MA caused it
161 if (mapEvent.oldValue().value().maintenanceAssociationList().size() >
162 mapEvent.newValue().value().maintenanceAssociationList().size()) {
163 Set<MaIdShort> newMaIds = mapEvent.newValue().value().maintenanceAssociationList()
164 .stream()
165 .map(MaintenanceAssociation::maId)
166 .collect(Collectors.toSet());
167 Optional<MaintenanceAssociation> removedMa =
168 mapEvent.oldValue().value().maintenanceAssociationList()
169 .stream()
170 .filter(maOld -> !newMaIds.contains(maOld.maId())).findFirst();
171 if (removedMa.isPresent()) {
172 maId = removedMa.get().maId();
173 }
174 type = MdEvent.Type.MA_REMOVED;
175 } else if (mapEvent.oldValue().value().maintenanceAssociationList().size() <
176 mapEvent.newValue().value().maintenanceAssociationList().size()) {
177 Set<MaIdShort> oldMaIds = mapEvent.oldValue().value().maintenanceAssociationList()
178 .stream()
179 .map(MaintenanceAssociation::maId)
180 .collect(Collectors.toSet());
181 Optional<MaintenanceAssociation> addedMa =
182 mapEvent.newValue().value().maintenanceAssociationList()
183 .stream()
184 .filter(maNew -> !oldMaIds.contains(maNew.maId())).findFirst();
185 if (addedMa.isPresent()) {
186 maId = addedMa.get().maId();
187 }
188 type = MdEvent.Type.MA_ADDED;
189 } else {
190 type = MdEvent.Type.MD_UPDATED;
191 }
Sean Condon0e89bda2017-03-21 14:23:19 +0000192 break;
193 case REMOVE:
194 default:
195 type = MdEvent.Type.MD_REMOVED;
196 break;
197 }
Sean Condon96b896d2017-12-11 12:44:29 -0800198 if (mapEvent.oldValue() != null && mapEvent.oldValue().value() != null) {
199 MaintenanceDomain oldMd = mapEvent.oldValue().value();
200 try {
201 if (maId != null) {
202 notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd, maId));
203 } else {
204 notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd));
205 }
206 } catch (CfmConfigException e) {
207 log.warn("Unable to copy MD {}", oldMd);
208 notifyDelegate(new MdEvent(type, mapEvent.key()));
209 }
210 } else {
211 notifyDelegate(new MdEvent(type, mapEvent.key()));
212 }
Sean Condon0e89bda2017-03-21 14:23:19 +0000213 }
214 }
215}