blob: 5723466b0e1782098082a43388a6783867fe717b [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 static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.ArrayList;
21import java.util.Collection;
22
23import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
28import org.apache.felix.scr.annotations.Service;
29import org.onosproject.core.CoreService;
30import org.onosproject.core.IdGenerator;
31import org.onosproject.event.AbstractListenerManager;
32import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
33import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry;
34import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate;
35import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate;
36import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort;
37import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
38import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
39import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
40import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
41import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepEvent;
42import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepListener;
43import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
44import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
45import org.onosproject.mastership.MastershipService;
46import org.onosproject.net.Device;
47import org.onosproject.net.DeviceId;
48import org.onosproject.net.device.DeviceEvent;
49import org.onosproject.net.device.DeviceListener;
50import org.onosproject.net.device.DeviceService;
51import org.slf4j.Logger;
52
53/**
54 * Provides implementation of the CFM North and South Bound Interfaces.
55 */
56@Component(immediate = true)
57@Service
58public class CfmMepManager
59 extends AbstractListenerManager<CfmMepEvent, CfmMepListener>
60 implements CfmMepService {
61
62 private final Logger log = getLogger(getClass());
63
64 private final DeviceListener deviceListener = new InternalDeviceListener();
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected DeviceService deviceService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected CoreService coreService;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected MastershipService mastershipService;
74
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected CfmMdService cfmMdService;
77
78 private static final int DEFAULT_POLL_FREQUENCY = 30;
79 private int fallbackMepPollFrequency = DEFAULT_POLL_FREQUENCY;
80
81 private IdGenerator idGenerator;
82
83 //FIXME Get rid of this hack - we will use this in memory to emulate
84 // a store for the short term.
85 //Note: This is not distributed and will not work in a clustered system
86 //TODO Create a MepStore for this
87 private Collection<Mep> mepCollection;
88
89
90 @Activate
91 public void activate() {
92 //FIXME Get rid of this local list
93 mepCollection = new ArrayList<>();
94
95 eventDispatcher.addSink(CfmMepEvent.class, listenerRegistry);
96 deviceService.addListener(deviceListener);
97 idGenerator = coreService.getIdGenerator("mep-ids");
98 log.info("CFM MEP Manager Started");
99 }
100
101 @Deactivate
102 public void deactivate() {
103 deviceService.removeListener(deviceListener);
104 eventDispatcher.removeSink(CfmMepEvent.class);
105 log.info("CFM MEP Manager Stopped");
106 mepCollection.clear();
107 }
108
109 @Override
110 public Collection<MepEntry> getAllMeps(MdId mdName, MaIdShort maName)
111 throws CfmConfigException {
112 //Will throw IllegalArgumentException if ma does not exist
113 cfmMdService.getMaintenanceAssociation(mdName, maName);
114
115 Collection<MepEntry> mepEntryCollection = new ArrayList<>();
116
117 for (Mep mep:mepCollection) {
118 if (mep.mdId().equals(mdName) && mep.maId().equals(maName)) {
119 DeviceId mepDeviceId = mep.deviceId();
120 if (deviceService.getDevice(mepDeviceId) == null) {
121 log.warn("Device not found/available " + mepDeviceId +
122 " for MEP: " + mdName + "/" + maName + "/" + mep.mepId());
123 continue;
124 } else if (!deviceService.getDevice(mepDeviceId)
125 .is(CfmMepProgrammable.class)) {
126 throw new CfmConfigException("Device " + mepDeviceId +
127 " does not support CfmMepProgrammable behaviour.");
128 }
129
130 log.debug("Retrieving MEP results for Mep {} in MD {}, MA {} "
131 + "on Device {}", mep.mepId(), mdName, maName, mepDeviceId);
132 mepEntryCollection.add(deviceService
133 .getDevice(mepDeviceId)
134 .as(CfmMepProgrammable.class)
135 .getMep(mdName, maName, mep.mepId()));
136 }
137 }
138
139 return mepEntryCollection;
140 }
141
142 @Override
143 public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
144 //Will throw IllegalArgumentException if ma does not exist
145 cfmMdService.getMaintenanceAssociation(mdName, maName);
146
147 for (Mep mep : mepCollection) {
148 if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
149 && mep.mepId().equals(mepId)) {
150
151 DeviceId mepDeviceId = mep.deviceId();
152 if (deviceService.getDevice(mepDeviceId) == null) {
153 throw new CfmConfigException("Device not found " + mepDeviceId);
154 } else if (!deviceService.getDevice(mepDeviceId).is(CfmMepProgrammable.class)) {
155 throw new CfmConfigException("Device " + mepDeviceId +
156 " does not support CfmMepProgrammable behaviour.");
157 }
158
159 log.debug("Retrieving MEP reults for Mep {} in MD {}, MA {} on Device {}",
160 mep.mepId(), mdName, maName, mepDeviceId);
161
162 return deviceService.getDevice(mepDeviceId)
163 .as(CfmMepProgrammable.class).getMep(mdName, maName, mepId);
164 }
165 }
166 return null;
167 }
168
169 @Override
170 public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
171 //Will throw IllegalArgumentException if ma does not exist
172 cfmMdService.getMaintenanceAssociation(mdName, maName);
173
174 for (Mep mep : mepCollection) {
175 if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
176 && mep.mepId().equals(mepId)) {
177 Device mepDevice = deviceService.getDevice(mep.deviceId());
178 if (mepDevice == null || !mepDevice.is(CfmMepProgrammable.class)) {
179 throw new CfmConfigException("Unexpeced fault on device drier for "
180 + mep.deviceId());
181 }
182 boolean deleted = false;
183 try {
184 deleted = mepDevice.as(CfmMepProgrammable.class)
185 .deleteMep(mdName, maName, mepId);
186 } catch (CfmConfigException e) {
187 log.warn("MEP could not be deleted on device - perhaps it "
188 + "does not exist. Continuing");
189 mepCollection.remove(mep);
190 return false;
191 }
192 if (deleted) {
193 mepCollection.remove(mep);
194 return true;
195 } else {
196 return false;
197 }
198 }
199 }
200 return false;
201 }
202
203 @Override
204 public boolean createMep(MdId mdName, MaIdShort maName, Mep newMep) throws CfmConfigException {
205 log.debug("Creating MEP " + newMep.mepId() + " on MD {}, MA {} on Device {}",
206 mdName, maName, newMep.deviceId().toString());
207 for (Mep mep : mepCollection) {
208 if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
209 && mep.mepId().equals(newMep.mepId())) {
210 return false;
211 }
212 }
213
214 //Will throw IllegalArgumentException if ma does not exist
215 cfmMdService.getMaintenanceAssociation(mdName, maName);
216
217 DeviceId mepDeviceId = newMep.deviceId();
218 if (deviceService.getDevice(mepDeviceId) == null) {
219 throw new CfmConfigException("Device not found " + mepDeviceId);
220 } else if (!deviceService.getDevice(mepDeviceId).is(CfmMepProgrammable.class)) {
221 throw new CfmConfigException("Device " + mepDeviceId + " does not support CfmMepProgrammable behaviour.");
222 }
223
224 boolean deviceResult =
225 deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class).createMep(mdName, maName, newMep);
226 log.debug("MEP created on {}", mepDeviceId);
227 if (deviceResult) {
228 return mepCollection.add(newMep);
229 } else {
230 return deviceResult;
231 }
232 }
233
234 @Override
235 public void transmitLoopback(MdId mdName, MaIdShort maName,
236 MepId mepId, MepLbCreate lbCreate) throws CfmConfigException {
237 for (Mep mep : mepCollection) {
238 if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
239 && mep.mepId().equals(mepId)) {
240 log.debug("Transmitting Loopback on MEP {}/{}/{} on Device {}",
241 mdName, maName, mepId, mep.deviceId());
242 deviceService.getDevice(mep.deviceId())
243 .as(CfmMepProgrammable.class)
244 .transmitLoopback(mdName, maName, mepId, lbCreate);
245 return;
246 }
247 }
248 throw new CfmConfigException("Mep " + mdName + "/" + maName + "/"
249 + mepId + " not found when calling Transmit Loopback");
250 }
251
252 @Override
253 public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId)
254 throws CfmConfigException {
255 for (Mep mep : mepCollection) {
256 if (mep.mdId().equals(mdName) && mep.maId().equals(maName)
257 && mep.mepId().equals(mepId)) {
258 log.debug("Aborting Loopback on MEP {}/{}/{} on Device {}",
259 mdName, maName, mepId, mep.deviceId());
260 deviceService.getDevice(mep.deviceId())
261 .as(CfmMepProgrammable.class)
262 .abortLoopback(mdName, maName, mepId);
263 return;
264 }
265 }
266 throw new CfmConfigException("Mep " + mdName + "/" + maName + "/"
267 + mepId + " not found when calling Transmit Loopback");
268 }
269
270 @Override
271 public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
272 MepLtCreate ltCreate) {
273 throw new UnsupportedOperationException("Not yet implemented");
274 }
275
276 private class InternalDeviceListener implements DeviceListener {
277 @Override
278 public void event(DeviceEvent event) {
279 switch (event.type()) {
280 case DEVICE_REMOVED:
281 case DEVICE_AVAILABILITY_CHANGED:
282 DeviceId deviceId = event.subject().id();
283 if (!deviceService.isAvailable(deviceId)) {
284 log.warn("Device {} has been removed or changed", deviceId);
285 }
286 break;
287 default:
288 break;
289 }
290 }
291 }
292}